Skip to content

Writing scripts

Igor Petruk edited this page Jul 24, 2024 · 14 revisions

Your first script

The best way to start a new script is to generate the basic one from a template. List all available templates:

$ scriptisto new
Usage: scriptisto new <lang> | tee ./new-script
Available languages: [
    "c",
    "chicken",
    "cpp",
    "crystal",
    ...
]

Tip: You can add or redefine your script templates with scriptisto template command.

Now generate a new script. For example for Haskell:

$ scriptisto new haskell | tee script.hs
#!/usr/bin/env scriptisto

-- scriptisto-begin
-- script_src: script.hs
-- build_cmd: ghc -O -o script script.hs && strip ./script
-- scriptisto-end

main = putStrLn "Hello, Haskell!"

Chmod and run it

$ chmod +x script.hs
$ ./script.hs
Hello, Haskell!

Try to run it second time - this time it will be very fast! scriptisto re-used the native optimized Haskell binary it built during the first run. To learn how to force rebuilds see Control Build Trigger section.

Configuration in the comments

A little secret - scriptisto does not know it is a comment. It knows nothing about the language you use. Basically it looks for it's config in YAML format like this

...
...   scriptisto-begin
...   <--
...   <-- CONFIG HERE.
...   <-- 
...   scriptisto-end
...

Everything to the left of the scriptisto- indentation, or text higher or lower the scriptisto- block is ignored. Now you understand that for scriptisto a comment in C

// scriptisto-begin
// script_src: main.c
// build_cmd: clang -O2 main.c -o ./script
// scriptisto-end

Turns to a YAML config

script_src: main.c
build_cmd: clang -O2 main.c -o ./script

You can freely put your config after your main code, this is a matter of style and preference.

Build process

scriptisto hashes your script to detect if it is new or has changed since. Moving a script at the moment also invalidates cache. This is how it builds your app with simplest configs like above:

  1. Create cache directory for the program in the user home directory and change directory there
  2. Write a source code of your script to a path, specified via script_src. (Blank the "shebang" line)
  3. Run a command specified via the build_cmd. If fails, print build logs and exit.
  4. Exec to target_bin (./script by default) passing command lines arguments correctly.

If after parsing your YAML config and hashing source file scriptisto detects no changes since the last build, it just runs exec immediately.

The next section contains many more exciting options that can alter the build process.

Configuration options

The configuration is a single BuildSpec entry:

Field Default Description
script_src Mandatory to specify Under which filename to write your script in a cache directory, so build_cmd can use it
build_cmd Build command to run. Runs under sh
build_once_cmd Build command to run on the first run only.
target_bin ./script A binary to exec to if the build was successful. This is a path, not a shell command!
target_interpreter If specified, execs to this interpreter instead, passing target_bin and command arguments as arguments to this binary. Not a shell command, but a space separated list of simple strings. First string will be a target of exec. Example: target_intepreter: /usr/bin/env deno --no-prompt, target_bin: ./script.bundle.js because you cannot directly exec to ./script.bundle.js.
replace_shebang_with Empty string Before building, replace this scriptisto "shebang" with this string. Use case 1: Make languages that don't support "shebangs" or requiring certain text in the first line happy. Use case 2: For languages that support shebangs you can put their native one there, but initially use scriptisto for other work
files Empty list A list of File entries to write additional files before build
docker_build Enables build in a docker container. See Builds in Docker section.

File entry:

Field Default Description
path Mandatory to specify A file path
content Mandatory to specify A file content

We recommend using YAML multiline syntax to specify files. Watch out for the indentation: the first line of the file in content determines the indentation for the rest of the content.

files:
  - path: ./file1
    content: |
      First line
      Second line
  - path: ./file2
    content: |
      First line in file1

If your program is built from multiple files, we recommend using the script contents for the largest, "main" file and files entries in YAML for smaller files, such as package manager configs, build or docker scripts.

Builds in Docker

With scriptisto you can build your binary in an automatically managed Docker container, without having compilers installed on host. If you build your binary statically, you will be able to run it on host. There are a lot if images that help you building static binaries, starting from alpine offering a MUSL toolchain, to more specialized images.

Find some docker-* templates via scriptisto new command.

Examples: C, Rust. No need to have anything but Docker installed!

Builds in Docker enabled by populating the docker_build config entry, defined as such:

Field Default Description
dockerfile Mandatory to specify A multiline content of a Dockerfile to make your image. In the simplest form use dockerfile: FROM my_image to use my_image from Docker Hub as is.
src_mount_dir If specified, mount your source cache directory to this path in container. For example your script_src will be here.
extra_args empty Extra args to pass to a docker run command. Example: extra_args: [-v,cargo-cache:/root/.cargo/registry] to cache cargo artifacts between builds.

scriptisto produces and reuses scriptisto-* Docker images on your machine. Remove them to rebuild them from scratch (e.g. with newer software).

Clone this wiki locally