:foo-bar |
"baz" |
The standard library is the set of modules that come with Bass.
The ground module is inherited by all modules. It provides basic language constructs and the standard toolkit for running thunks.
$ |
constructs a thunk with args |
$$ |
constructs a thunk with args passed to its entrypoint |
* |
multiplies numbers |
+ |
sums numbers |
- |
subtracts ys from x |
-> |
passes a value through a series of function calls |
< |
returns true if the numbers are in ascending order |
<= |
returns true if the numbers are in ascending or equal order |
= |
returns true if the values are all equal |
> |
returns true if the numbers are in descending order |
>= |
returns true if the numbers are in descending or equal order |
across |
returns a pipe source that yields a list of values across all the given sources |
addr |
returns an address for a port provided by the thunk |
always |
returns a function that returns x for any value |
and |
returns a truthy value if none of the conds return a falsy value |
append |
joins all given lists into one listdeprecated |
applicative? |
returns true if the value is an applicative |
apply |
call an applicative's underlying operative with a list of arguments |
assert |
applies the predicate to its arguments and errors if it returns false |
assoc |
assoc(iate) keys with values in a clone of a scope |
bind |
attempts to bind values in the scope |
binds? |
returns true if the scope has a value bound to the given symbol |
boolean? |
returns true if the value is true or false |
cache-dir |
returns a cache directory with the given identifier and concurrency mode |
case |
evaluates the branch that successfully binds the given value |
cd |
chain a sequence of thunks with a given working directory |
collect |
returns (f value) for every value read from the source |
combiner? |
returns true if the value is a combiner |
concat |
joins all given lists into one list |
cond |
if-then-else, but with many clauses |
conj |
conjoins values onto the end of a list |
cons |
construct a pair from the given values |
current-scope |
returns the scope of the caller |
curryfn |
returns a fn which accepts args one value at a time |
def |
bind symbols to values in the current scope |
defn |
construct a function and bind it to a symbol |
defop |
construct an operative and bind it to a symbol |
do |
evaluate a sequence, returning the last value |
doc |
print docs for symbols |
docker-build |
returns a thunk built from a Dockerfile in the context directory |
dump |
encodes a value as JSON to stderr |
each |
calls f for every value read from the source |
emit |
emits a value to a sink |
empty? |
returns true if the value is an empty list, a zero-length string, an empty scope, or null |
error |
errors with the given message |
eval |
evaluate a value in a scope |
except-globs |
returns a path with the given globs excluded |
export |
returns a virtual file containing the thunk as an OCI tarball |
filter |
returns only values from xs which satisfy the predicate |
first |
return the first value in a pair |
fn |
construct a function |
foldl |
reduces xs, leftmost values first, with initial value z |
foldr |
reduces xs, rightmost values first, with initial value z |
for |
loops over values from sources |
from |
chain a sequence of thunks starting from an initial image |
glob |
returns a path narrowed to paths matching the given glob patterns |
id |
identity function; returns its argument |
if |
if then else (branching logic) |
ignore? |
returns true if the value is _ ("ignore") |
import |
binds symbols in the current scope to their values from the source scope |
insecure! |
sets the :insecure field of the thunk to true |
json |
returns a string containing val encoded as JSON |
keys |
collects the bindings from a scope |
last |
returns the last value from the source |
length |
return the length of the given list |
let |
binds values in a child scope |
linux |
a path root for resolving Linux images |
list |
construct a list from a sequence of values |
list* |
prepend a sequence of values to a list given as the final argument |
list->scope |
constructs an object from a list of flat keyword/value pairs |
list->source |
creates a pipe source from a list of values in chronological order |
list? |
returns true if the value is a linked list |
load |
load a thunk as a module |
log |
logs a string message or arbitrary value to stderr |
make-scope |
construct a scope with the given parents |
map |
returns a list containing the result of applying f to each member of xs |
map-pairs |
calls a function with alternating pairs in a flat list (i.e. with pairs ungrouped) |
mask |
shrouds a string in secrecy |
max |
returns the largest number |
memo |
memo(ize)s a function |
merge |
returns a scope containing the union of the given scopes |
meta |
returns the meta attached to the value |
min |
returns the smallest number |
mkfile |
returns an in-memory file with the given content |
mkfs |
returns a dir path backed by an in-memory filesystem |
module |
returns a scope with only the specified bindings from a child scope |
next |
receive the next value from a source |
not |
negates the given bool-ish value |
now |
returns the current UTC time truncated to the given seconds |
null? |
returns true if the value is null |
number? |
returns true if the value is a number |
oci-load |
returns a thunk loaded from an OCI image tarball |
only-globs |
returns a path with the given globs as the only included files |
op |
construct an operative |
operative? |
returns true if the value is an operative |
or |
returns the first truthy value returned by evaluating conds |
pair? |
returns true if the value is a pair |
path-base |
returns the path-name converted into a file path |
path-name |
returns the base name of the path |
path-stem |
returns the base name of the path, without any extension |
path? |
returns true if the value is a path |
provide |
provide bindings to the current scope from a nested scope |
publish |
publishes the thunk to a container registry |
read |
returns a stream producing values read from a thunk's output or a file's content |
recall-memo |
fetches the result of a memoized function call |
reduce-kv |
reduces a scope |
refute |
applies the predicate to its arguments and errors if it returns true |
resolve |
resolve an image reference to its most exact form |
rest |
return the second value in a pair, i.e. the rest of a linked list |
run |
runs a thunk |
scope->list |
returns a flat list alternating a scope's keys and values |
scope? |
returns true if the value is a scope |
scratch |
an empty thunk |
second |
return the second member of a linked list |
sink? |
returns true if the value is a sink |
source? |
returns true if the value is a source |
start |
starts running a thunk asynchronously |
store-memo |
stores the result of a memoized function call |
str |
returns the concatenation of all given strings or values |
string->cmd-path |
converts a string to a command or file path |
string->dir |
converts a string to a directory path |
string->fs-path |
parses a string value into a file or directory path |
string->symbol |
convert a string to a symbol |
string? |
returns true if the value is a string |
subpath |
extend path with another path |
substring |
returns a portion of a string |
succeeds? |
returns true if the thunk successfully runs (i.e. exit code 0) |
symbol->string |
convert a symbol to a string |
symbol? |
returns true if the value is a symbol |
take |
reads the next n values from the source into a list |
take-all |
reads all values from the source into a list |
third |
return third member of a linked list |
thunk-args |
returns the arguments to the thunk's command |
thunk-cmd |
returns the thunk's full command and args |
thunk? |
returns true if the value is a valid thunk |
trim |
removes whitespace from both ends of a string |
unwrap |
returns an applicative's underlying combiner |
use |
loads each thunk and binds it as the name from the thunk's command path |
vals |
collects the values from a scope |
wait |
waits for all started thunks to finish |
when |
evaluates the body if test returns true |
with-args |
returns thunk with args set to args |
with-cmd |
returns the thunk's full command and argumentss |
with-default-args |
returns thunk with default args set to args |
with-dir |
returns thunk with the working directory set to dir |
with-entrypoint |
returns thunk with entrypoint set to entrypoint |
with-entrypoint-args |
returns thunk with default args set to args |
with-env |
returns thunk with env set to the given env |
with-image |
returns thunk with the base image set to image |
with-insecure |
returns thunk with the insecure flag set to bool |
with-label |
returns thunk with the label set to val |
with-meta |
returns val with the given scope as its metadata |
with-mount |
returns thunk with a mount from source to the target path |
with-port |
returns thunk with a named port appended to its ports |
with-stdin |
returns thunk with stdin set to vals |
with-tls |
returns thunk with paths to a TLS certificate and key to generate |
wrap |
construct an applicative from a combiner (typically an operative) |
wrap-cmd |
prepend a command + args to a thunk's command + args |
write |
writes the source to the destination path |
(mkfs & file-content-kv)
applicative? combiner?
returns a dir path backed by an in-memory filesystem
Takes alternating file paths and their content, which must be a text string, and returns the root directory of an in-memory filesystem containing the specified files.
All embedded files have 0644 Unix file permissions and a zero (Unix epoch) mtime.
=> docker-image://docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.02s]=> mkfile /file [0.01s]=> cat <fs>/file [0.24s]▕ hey
"hey"
(log val & fields)
applicative? combiner?
(error msg & fields)
applicative? combiner?
errors with the given message
Accepts key-value fields for structured error data.
(error "oh no!")
error! call trace (oldest first):┆ <fs>/literate-4:1:0..1:161 │ (error "oh no!")^^^^^^^^^^^^^^^^oh no!
(error "oh no!" :exit-code 2)
error! call trace (oldest first):┆ <fs>/literate-4:1:0..1:291 │ (error "oh no!" :exit-code 2)^^^^^^^^^^^^^^^^^^^^^^^^^^^^^oh no!:exit-code 2
(wrap comb)
applicative? combiner?
(make-scope & parents)
applicative? combiner?
construct a scope with the given parents
(make-scope {:a 1} {:b 2})
{
{
} |
|||
{
} |
}
(eval [+ :a :b] (make-scope {:a 1} {:b 2}))
3
(bind scope formals val)
applicative? combiner?
attempts to bind values in the scope
Returns true if the binding succeeded, otherwise false.
(if (bind (current-scope) :abc 123) abc :mismatch)
123
(if (bind (current-scope) [] 123) _ :mismatch)
mismatch
(doc & symbols)
operative? combiner?
(applicative? val)
applicative? combiner?
(operative? val)
applicative? combiner?
returns true if the value is an operative
An operative is a combiner that is given the caller's scope.
An operative may decide whether and how to evaluate its arguments. They are typically used to define new syntactic constructs.
false
(operative? op)
true
(list->source list)
applicative? combiner?
creates a pipe source from a list of values in chronological order
(list->source [1 2 3])
<source: 1 2 3>
(across & sources)
applicative? combiner?
returns a pipe source that yields a list of values across all the given sources
Each list has the last value for each source. Values from each source are never skipped, but not every combination will be produced.
(def evens (list->source [0 2 4]))
evens
(def odds (list->source [1 3 5]))
odds
(next src & default)
applicative? combiner?
receive the next value from a source
If the source has ended, no value will be available. A default value may be provided, otherwise an error is raised.
(next (list->source [1]) :eof)
1
(next *stdin* :eof)
eof
(reduce-kv f init kv)
applicative? combiner?
(symbol->string sym)
applicative? combiner?
convert a symbol to a string
(symbol->string :hello!)
"hello!"
(string->symbol str)
applicative? combiner?
convert a string to a symbol
(string->symbol "hello!")
hello!
(scope->list obj)
applicative? combiner?
returns a flat list alternating a scope's keys and values
(scope->list {:a 1 :b 2 :c 3})
(
a
1
b
2
c
3
)
(apply assoc (cons {:d 4} (scope->list {:a 1 :b 2 :c 3})))
{
:d |
4 |
:a |
1 |
:b |
2 |
:c |
3 |
}
(string->fs-path str)
applicative? combiner?
parses a string value into a file or directory path
(string->fs-path "./file")
./file
(string->fs-path "file")
./file
(string->fs-path "dir/")
./dir/
(string->cmd-path str)
applicative? combiner?
converts a string to a command or file path
If the value contains a /, it is converted into a file path.
Otherwise, the given value is converted into a command path.
(string->cmd-path "scripts/foo")
./scripts/foo
(string->cmd-path "bash")
.bash
(string->dir str)
applicative? combiner?
converts a string to a directory path
A trailing slash is not required; the path is always assumed to be a directory.
(string->dir "dir")
./dir/
(string->dir "dir/")
./dir/
(path-name path)
applicative? combiner?
returns the base name of the path
For a command path, this returns the command name.
For a file or dir path, it returns the file or dir name.
For a file path, it returns the file name.
For a thunk, it returns the thunk's hash.
(path-name .bash)
"bash"
(path-name ./some/file)
"file"
(path-name ./some/dir/)
"dir"
(path-name (.tests))
"31TBBNE4GQGI0"
(with-image thunk image)
applicative? combiner?
returns thunk with the base image set to image
Image is either a thunk? or an image ref.
Recurses when thunk's image is another thunk, setting the deepest ref or unset image.
(with-image ($ go test ./...) (linux/golang))
{
:image |
{
} |
||||||||||||||
:args |
(
) |
}
(with-dir thunk dir)
applicative? combiner?
returns thunk with the working directory set to dir
Unlike cd
, the value of with-dir
is resolved at runtime, meaning it can use container-local paths.
If the thunk needs to write to its output directory, the output path passed to the command must be relative to the given dir. Thunk paths and other mounts will always be 1 level deep in the output directory, so use ../ to refer to back to the output directory, repeated for each additional level of depth. If the depth is unknown, you should use cd
instead.
(with-dir (.tests) ./src/)
{
:args |
(
) |
:dir |
./src/ |
}
(with-entrypoint thunk entrypoint)
applicative? combiner?
returns thunk with entrypoint set to entrypoint
(with-entrypoint-args thunk args)
applicative? combiner?
returns thunk with default args set to args
(with-stdin thunk vals)
applicative? combiner?
returns thunk with stdin set to vals
(with-stdin ($ jq ".a") [{:a 1} {:a 2}])
{
:args |
(
) |
||||
:stdin |
(
) |
}
(with-insecure thunk bool)
applicative? combiner?
returns thunk with the insecure flag set to bool
The insecure flag determines whether the thunk runs with elevated privileges, and is named to be indicate the reduced security assumptions.
(with-insecure (.boom) true)
{
:insecure |
true |
:args |
(
) |
}
(= (.boom) (with-insecure (.boom) false))
true
(with-label thunk name val)
applicative? combiner?
returns thunk with the label set to val
Labels are used to set metadata on a thunk, and are not used by the thunk itself.
When the thunk is exported or published, labels will be included in the OCI image.
(with-label ($ sleep 10) :at (now 10))
{
:args |
(
) |
||
:labels |
{
} |
}
(with-mount thunk source target)
applicative? combiner?
returns thunk with a mount from source to the target path
(with-mount ($ find ./inputs/) *dir*/inputs/ ./inputs/)
{
:args |
(
) |
||||
:mounts |
(
) |
}
(thunk-args thunk)
applicative? combiner?
returns the arguments to the thunk's command
(thunk-args ($ foo abc))
(
"abc"
)
(thunk-args ($ foo))
(
)
(resolve platform ref)
applicative? combiner?
resolve an image reference to its most exact form
(resolve {:platform {:os "linux"} :repository "golang" :tag "latest"})
=> resolve image config for docker.io/library/golang:latest [0.16s]
{
:image |
{
} |
}
(start thunk handler)
applicative? combiner?
starts running a thunk asynchronously
If the thunk errors or exits nonzero the handler is called with a combiner that raises the error when called.
If the thunk runs succeeds the handler is called with null.
=> docker-image://docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> banana ERROR [0.18s]▕ start: exec: "banana": executable file not found in $PATH!!! banana6: [0.13s] start: exec: "banana": executable file not found in $PATH
false
=> docker-image://docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> echo [0.23s]▕
true
=> docker-image://docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> banana ERROR [0.20s]▕ start: exec: "banana": executable file not found in $PATH!!! banana2: [0.14s] start: exec: "banana": executable file not found in $PATHerror! call trace (oldest first):┆ <fs>/literate-9:1:0..1:491 │ ((start (from (linux/alpine) ($ banana)) raiser))^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^resolve failed: exit code: 1run summary:=> docker-image://docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126=> banana [0.20s]start: exec: "banana": executable file not found in $PATHERROR: exit code: 1for more information, refer to the full output above
=> docker-image://docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> echo CACHED [0.00s]
null
(read thunk-or-file protocol)
applicative? combiner?
returns a stream producing values read from a thunk's output or a file's content
=> docker-image://docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.02s]=> echo 42 [0.19s]▕ 42
42
=> docker-image://docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> sh -c "echo 42 > file" [0.18s]
42
(cache-dir id & mode)
applicative? combiner?
returns a cache directory with the given identifier and concurrency mode
Cache directories may be mounted to thunks. Their content persists across thunk runs.
The :shared concurrency mode allows multiple thunks to run concurrently with the same cache.
The :locked mode allows only one thunk to run at a time with the same cache.
The :private mode creates a new mount for concurrent thunks.
The default mode is :shared.
(cache-dir "foo")
<cache: foo>/
(cache-dir "foo" :locked)
<cache: foo>/
(binds? scope sym)
applicative? combiner?
returns true if the scope has a value bound to the given symbol
(binds? {:x 1} :x)
true
(binds? {} :x)
false
(binds? (current-scope) :binds?)
true
(write src dest)
applicative? combiner?
writes the source to the destination path
Source is any value that can be passed to (read), i.e. a thunk or a path.
Writes are atomic. The content will first be written to dest.new and renamed to dest.
=> docker-image://docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> echo "Hello, world!" CACHED [0.00s]
null
(publish src ref)
applicative? combiner?
publishes the thunk to a container registry
Returns a fully qualified image reference.
=> resolve image config for docker.io/library/golang@sha256:403f48633fb5ebd49f9a2b6ad6719f912df23dae44974a0c9445be331e72ff5e [0.01s]=> docker-image://docker.io/library/golang@sha256:403f48633fb5ebd49f9a2b6ad6719f912df23dae44974a0c9445be331e72ff5e CACHED [0.00s]-> resolve docker.io/library/golang@sha256:403f48633fb5ebd49f9a2b6ad6719f912df23dae44974a0c9445be331e72ff5e [0.01s]=> go version [0.56s]▕ go version go1.20.3 linux/amd64=> exporting to image ERROR [0.28s]-> exporting layers [0.03s]-> exporting manifest sha256:ee2ec49bde927afbf361c4129b13688afab41e5e5909e2e8d6e6b18f135bc243 [0.00s]-> exporting config sha256:ddf70c21b2c77339d3f6673112de8241b4cb755089f128912758add24d5e4c6b [0.00s]-> pushing layers [0.24s]!!! exporting to imageerror! call trace (oldest first):┆ <fs>/literate-3:1:0..1:701 │ (publish (from (linux/golang) ($ go version)) "basslang/publish-demo")^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^failed to solve: failed to push docker.io/basslang/publish-demo:latest: push access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failedTip: if this error is too cryptic, please open an issue:https://github.com/vito/bass/issues/new?labels=cryptic&template=cryptic-error-message.md
(export thunk)
applicative? combiner?
returns a virtual file containing the thunk as an OCI tarball
Note that the file can only be read once. You can either (read) it with the :tar protocol or (write) it to a host path.
=> docker-image://docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> echo "Hello, world!" CACHED [0.00s]=> resolve image config for docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> exporting to oci image format [0.01s]-> exporting layers [0.00s]-> exporting manifest sha256:8dc66a54dc3c9385d4a1876a6c12dceffa9d4f151c9fbf7407144727900f5a63 [0.00s]-> exporting config sha256:6def8e016ef8a4a0d1d69a3bf033ef295e5c6ef804ae7eac0213c5446debc45b [0.00s]-> sending tarball [0.01s]
null
=> docker-image://docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> echo "Hello, world!" CACHED [0.00s]=> resolve image config for docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> exporting to oci image format [0.00s]-> exporting layers [0.00s]-> exporting manifest sha256:8dc66a54dc3c9385d4a1876a6c12dceffa9d4f151c9fbf7407144727900f5a63 [0.00s]-> exporting config sha256:6def8e016ef8a4a0d1d69a3bf033ef295e5c6ef804ae7eac0213c5446debc45b [0.00s]-> sending tarball [0.00s]
<fs>/blobs/
(only-globs path & globs)
applicative? combiner?
returns a path with the given globs as the only included files
See also (glob).
(only-globs *dir* ./**/*.go)
<host: /tmp/bass-scope105293759>/?[./**/*.go]
(except-globs path & globs)
applicative? combiner?
returns a path with the given globs excluded
See also (glob).
(except-globs *dir* ./.git/)
<host: /tmp/bass-scope2290460252>/![./.git/]
(mask secret name)
applicative? combiner?
shrouds a string in secrecy
Prevents the string from being revealed when the value is displayed.
Prevents the string from being revealed in a serialized thunk or thunk path.
Does NOT currently prevent the string's value from being displayed in log output; you still have to be careful there.
(mask "super secret" :github-token)
<secret: github-token (12 bytes)>
(defop name formals eformal & body)
operative? combiner?
(defn name formals & body)
operative? combiner?
construct a function and bind it to a symbol
Returns the bound symbol. Write a comment before or after to provide documentation.
(times-7 6)
42
(doc times-7)
--------------------------------------------------times-7 applicative? combiner?args: [x]multiplies by 7
null
(current-scope)
operative? combiner?
returns the scope of the caller
{
:*memos* |
<host: .>/bass.lock |
||||||||||||
{
} |
}
(eval [current-scope] {:a 1})
{
:a |
1 |
}
(map-pairs f ps)
applicative? combiner?
(let bindings & body)
operative? combiner?
(list->scope kwargs)
applicative? combiner?
constructs an object from a list of flat keyword/value pairs
(list->scope [:a 1 :b 2 :c 3])
{
:a |
1 |
:b |
2 |
:c |
3 |
}
(cond & clauses)
operative? combiner?
if-then-else, but with many clauses
Takes a flat pair sequence alternating tests to evaluate and an expression to evaluate if the test returns a truthy value.
Returns the result of the evaluated branch, or null if no tests were true.
By convention, :else is used as the final catch-all test, though any truthy value works.
(cond false :a false :b :else :c)
c
(cond true :a false :b :else :c)
a
(apply appv arg & opt)
applicative? combiner?
call an applicative's underlying operative with a list of arguments
A scope may be provided as the third argument. If not specified, the operative will be called in a new empty scope.
Used to call an applicative with pre-evaluated arguments, skipping the normal evaluation the applicative would perform prior to calling the underlying operative.
(-> x f & fs)
operative? combiner?
passes a value through a series of function calls
Given an input value and a series of functions, calls the first function with the input value, passing the output to the second function, and so on, returning the final value. Typically used to flatten a deeply nested function call to make it easier to read.
Functions are either a single form (i.e. a symbol) or a pair. A single form is called with the input value as the only argument. A pair is called with the input value prepended to the rest of the pair, i.e. inserted as the first argument.
(memo memos thunk binding)
applicative? combiner?
memo(ize)s a function
Returns a function equivalent to the binding from the load
ed thunk which caches its results to/from memos, a path to a file on the host (read-write) or from a thunk (read-only).
This is a utility for caching dependency version resolution, such as image tags and git refs. It is technically the only way to perform writes against the host filesystem.
The intended practice is to commit memos into source control to facilitate reproducible builds.
(def memos *dir*/bass.lock)
memos
(upper-cache "hello")
"HELLO"
=> docker-image://docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.02s]=> upload <host: /tmp/bass-scope1327887344>/bass.lock [0.01s]-> transferring /tmp/bass-scope1327887344: 423B [0.00s]=> copy /bass.lock /bass.lock [0.01s]=> cat <host: /tmp/bass-scope1327887344>/bass.lock [0.19s]▕ memos: {▕ module: {▕ args: {▕ command_path: {▕ name: "strings"▕ }▕ }▕ }▕ calls: {▕ binding: "upper-case"▕ results: {▕ input: {▕ array: {▕ values: {▕ string: {▕ value: "hello"▕ }▕ }▕ }▕ }▕ output: {▕ string: {▕ value: "HELLO"▕ }▕ }▕ }▕ }▕ }
null
(succeeds? thunk)
applicative? combiner?
returns true if the thunk successfully runs (i.e. exit code 0)
returns false if it fails (i.e. exit code nonzero)
Used for running a thunk as a conditional instead of erroring when it fails.
=> docker-image://docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> .false ERROR [0.17s]!!! .false
false
=> docker-image://docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.03s]=> .true [0.23s]
true
(run thunk)
applicative? combiner?
runs a thunk
Raises an error if the thunk's command fails (i.e. exit code 0)
Returns null.
=> docker-image://docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> echo "Hello, world!" CACHED [0.00s]=> resolve image config for docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]
null
(assert predicate & args)
operative? combiner?
(refute predicate & args)
operative? combiner?
(last source & default)
applicative? combiner?
returns the last value from the source
As with next
, a default may be provided to be returned when the source is empty. If not provided, an error will be raised if the source is empty.
(last (list->source [1 2 3]))
3
(each source f)
applicative? combiner?
(for bindings & body)
operative? combiner?
loops over values from sources
Takes a list alternating bindings and their sources, similar to let
. Reads values across all sources and evaluates the body for each set of values as they are read with next
.
Returns null when the source reaches its end.
(def evens (list->source [0 2 4]))
evens
(def odds (list->source [1 3 5]))
odds
(take n source)
applicative? combiner?
reads the next n values from the source into a list
(take 2 (list->source [1 2 3]))
(
1
2
)
(collect f source)
applicative? combiner?
returns (f value) for every value read from the source
(collect (fn [n] (+ n 1)) (list->source [1 2 3]))
(
2
3
4
)
(take-all source)
applicative? combiner?
reads all values from the source into a list
(take-all (list->source [1 2 3]))
(
1
2
3
)
(from image & thunks)
applicative? combiner?
chain a sequence of thunks starting from an initial image
(cd dir thunk & thunks)
applicative? combiner?
chain a sequence of thunks with a given working directory
Shorthand for using with-mount
to mount ./ on the first thunk and chaining the rest using from
. The working directory will propagate between them.
Typically used within an outer from
which sets the first thunk's image in order to join it into the chain.
{
:image |
{
} |
||||||||||||||
:args |
(
) |
||||||||||||||
:mounts |
(
) |
}
(linux & args)
operative? combiner?
a path root for resolving Linux images
Memoizes image resolution into the caller's *memos*, if set.
(linux/ubuntu)
{
:image |
{
} |
}
(linux/ubuntu :18.04)
{
:image |
{
} |
}
(linux/docker.io/library/ubuntu :18.04)
{
:image |
{
} |
}
(docker-build context platform & opts)
applicative? combiner?
returns a thunk built from a Dockerfile in the context directory
Additional parameters may be passed as opts:
:target specifies a target stage to build.
:args specifies build args from a scope with string values.
:dockerfile specifies a path to a Dockerfile within the context directory.
(docker-build *dir* {:os "linux"})
{
:image |
{
} |
}
(docker-build *dir* {:os "linux"} :target "foo")
{
:image |
{
} |
}
(docker-build *dir* {:os "linux"} :dockerfile ./Dockerfile.foo)
{
:image |
{
} |
}
(docker-build *dir* {:os "linux"} :args {:FOO "bar"})
{
:image |
{
} |
}
(oci-load file platform & opts)
applicative? combiner?
(glob path & patterns)
operative? combiner?
returns a path narrowed to paths matching the given glob patterns
To exclude a glob, place a ! argument ahead of it. Only the path immediately after it will be excluded.
(glob *dir* ./*.nix)
<host: /tmp/bass-scope3402046316>/?[./*.nix]
(glob *dir* ./*.nix ! ./foo.nix)
<host: /tmp/bass-scope3402046316>/?[./*.nix]![./foo.nix]
(glob *dir* ./*.nix ! ./foo.nix ./**/*.go ! ./main.go)
<host: /tmp/bass-scope3402046316>/?[./*.nix ./**/*.go]![./foo.nix ./main.go]
Bass modules always run as commands. Either a user runs the script with the bass
command, or another Bass module runs it as a thunk.
When a module is run as a script, the values reflect the system values available to the bass
command, and main
is called with the arguments passed to bass
.
When a module is run as a thunk, the values reflect the values set in the thunk, and main
is called with the thunk's args.
*dir* |
current working directory |
*env* |
environment variables |
*stdin* |
standard input stream |
*stdout* |
standard output sink |
main |
script entrypoint |
*env*
scope?
environment variables
System environment variables are only available to the entrypoint script. To propagate them further they must be explicitly passed to thunks using with-env
.
System environment variables are unset from the physical OS process as part of initialization to ensure they cannot be leaked.
{
:SECRET_TOKEN |
"im a spooky value" |
}
(main)
applicative? combiner?
script entrypoint
The [script:main] function is called with any provided command-line args when running a Bass script.
Scripts should define it to capture system arguments and run the script's desired effects.
Putting effects in [script:main] instead of running them at the toplevel makes the Bass language server happier.
.strings
module
Simple functions for manipulating UTF-8 encoded strings.
(load (.strings))
<scope: {{thunk KP8HLM3BB1O7E: .strings}}>
includes? |
returns true if str includes substr |
join |
joins a list of strings together with delim in between |
length |
returns the string's length |
split |
split a string on a delimiter |
upper-case |
capitalizes all letters in the string |
.git
module
Bare essentials for fetching Git repositories, using the git
CLI from an image passed on stdin
.
This module is limited to functions necessary for fetching other Bass scripts, i.e. bootstrapping.
checkout |
returns the repo checked out to the given ref |
github |
a path root for repos hosted at github.com |
ls-remote |
resolves a ref to a sha at the remote repo |
path |
returns a path root for repos at the given base URL |
(ls-remote repo ref & timestamp)
applicative? combiner?
resolves a ref to a sha at the remote repo
Does not cache. Used to resolve the ref at a point in time.
(git:ls-remote "https://github.com/vito/bass" "main")
=> resolve image config for docker.io/alpine/git@sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2 [0.02s]=> docker-image://docker.io/alpine/git@sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2 CACHED [0.00s]-> resolve docker.io/alpine/git@sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2 [0.01s]=> git ls-remote https://github.com/vito/bass main [1.54s]▕ 0537fa0323f1b12a43f0ab7dc90d2d00894d9c63 refs/heads/main
"0537fa0323f1b12a43f0ab7dc90d2d00894d9c63"
(checkout repo ref)
applicative? combiner?
returns the repo checked out to the given ref
The thunk for cloning the repo is labeled with the given ref. If the ref refers to a branch, you may want to resolve it to a sha first with [git:ls-remote] so that it's not cached forever.
Submodules are always initialized.
(git:checkout "https://github.com/vito/bass" "ea8cae6d4c871cb14448d7254843d86dbab8505f")
{
:image |
{
} |
||||||||||||||||||||||||||
:args |
(
) |
}
./
(path root memos)
applicative? combiner?
returns a path root for repos at the given base URL
Please omit the trailing slash. (TODO: would be nice to just strip it or somehow make it a non-issue.)
(def gh (git:path "https://github.com" null))
gh
gh/vito/bass/ref/main/
=> resolve image config for docker.io/alpine/git@sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2 [0.02s]=> docker-image://docker.io/alpine/git@sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2 CACHED [0.00s]-> resolve docker.io/alpine/git@sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2 [0.01s]=> git ls-remote https://github.com/vito/bass main [0.51s]▕ 0537fa0323f1b12a43f0ab7dc90d2d00894d9c63 refs/heads/main
{
:image |
{
} |
||||||||||||||||||||||||||
:args |
(
) |
}
./
(github & args)
operative? combiner?
a path root for repos hosted at github.com
Memoizes ref resolution into the caller's *memos*, if set.
git:github/vito/bass/sha/ea8cae6d4c871cb14448d7254843d86dbab8505f/
{
:image |
{
} |
||||||||||||||||||||||||||
:args |
(
) |
}
./
(git:github/vito/bass/sha/ "ea8cae6d4c871cb14448d7254843d86dbab8505f")
{
:image |
{
} |
||||||||||||||||||||||||||
:args |
(
) |
}
./
git:github/vito/bass/ref/main/
{
:image |
{
} |
||||||||||||||||||||||||||
:args |
(
) |
}
./
.time
module
(load (.time))
<scope: {{thunk 3AFD58R2RCI46: .time}}>
every-minute |
returns a timestamp of the current minute |
measure |
evaluates a form and and logs the time it took |
minute |
60 seconds |
monthly |
returns a timestamp of the current month |
yearly |
returns a timestamp of the current year |
(measure form)
operative? combiner?
evaluates a form and and logs the time it took
Returns the value returned by the form.
(use (.time))
(
time
)
(time:measure (sleep 1))
debug (time (sleep 1)) => null took 1.423512794s=> docker-image://docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:124c7d2707904eea7431fffe91522a01e5a861a624ee31d03372cc1d138a3126 [0.02s]=> sleep 1 [1.22s]
null
.regexp
module
(load (.regexp))
<scope: {{thunk FUG1RSA9RSV0G: .regexp}}>
case |
matches a string against regexp callback pairs |
bind symbols to values in the current scope
Supports destructuring assignment.
abc
(
a
b
c
)
(
"it's easy as"
1
2
3
)