{"id":13469014,"url":"https://github.com/stepchowfun/toast","last_synced_at":"2025-05-13T21:03:55.118Z","repository":{"id":37502630,"uuid":"182408739","full_name":"stepchowfun/toast","owner":"stepchowfun","description":"Containerize your development and continuous integration environments. 🥂","archived":false,"fork":false,"pushed_at":"2025-03-20T09:58:03.000Z","size":1134,"stargazers_count":1587,"open_issues_count":10,"forks_count":40,"subscribers_count":12,"default_branch":"main","last_synced_at":"2025-04-28T13:58:43.041Z","etag":null,"topics":["build-system","build-tool","ci","containers","continuous-integration","dev-environment","development-environment","docker"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stepchowfun.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":"FUNDING.yml","license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"stepchowfun"}},"created_at":"2019-04-20T13:22:09.000Z","updated_at":"2025-04-27T09:28:01.000Z","dependencies_parsed_at":"2023-11-22T14:47:50.841Z","dependency_job_id":"7c248100-677a-4e1f-93ac-6544b46a20f7","html_url":"https://github.com/stepchowfun/toast","commit_stats":{"total_commits":438,"total_committers":9,"mean_commits":"48.666666666666664","dds":"0.12557077625570778","last_synced_commit":"caf7f33f783bcc8ca1f7a5f946469333c41ce686"},"previous_names":[],"tags_count":62,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stepchowfun%2Ftoast","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stepchowfun%2Ftoast/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stepchowfun%2Ftoast/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stepchowfun%2Ftoast/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stepchowfun","download_url":"https://codeload.github.com/stepchowfun/toast/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254028083,"owners_count":22002179,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["build-system","build-tool","ci","containers","continuous-integration","dev-environment","development-environment","docker"],"created_at":"2024-07-31T15:01:24.430Z","updated_at":"2025-05-13T21:03:55.067Z","avatar_url":"https://github.com/stepchowfun.png","language":"Rust","readme":"# Toast 🥂\n\n[![Build status](https://github.com/stepchowfun/toast/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/stepchowfun/toast/actions?query=branch%3Amain)\n\n*Toast* is a tool for containerizing your workflows such as building and testing a project. You define tasks in a YAML file called a *toastfile*, and Toast runs them in a container based on a Docker image of your choosing. What constitutes a \"task\" is up to you: tasks can install system packages, compile an application, run a test suite, or even serve web pages. Tasks can depend on other tasks, so Toast can be understood as a high-level containerized build system.\n\n![Welcome to Toast.](https://raw.githubusercontent.com/stepchowfun/toast/main/media/welcome-0.svg?sanitize=true)\n\nHere's the toastfile for the example shown above:\n\n```yaml\nimage: ubuntu\ntasks:\n  install_gcc:\n    command: |\n      apt-get update\n      apt-get install --yes gcc\n\n  build:\n    dependencies:\n      - install_gcc\n    input_paths:\n      - main.c\n    command: gcc main.c\n\n  run:\n    dependencies:\n      - build\n    command: ./a.out\n```\n\nToast caches each task by committing the container to an image. The image is tagged with a cryptographic hash of the shell command for the task, the contents of the files copied into the container, and all the other task inputs. This hash allows Toast to skip tasks that haven't changed since the last run.\n\nIn addition to local caching, Toast can use a Docker registry as a remote cache. You, your teammates, and your continuous integration (CI) system can all share the same remote cache. Used in this way, your CI system can do all the heavy lifting like building and installing dependencies so you and your team can focus on development.\n\nRelated tools:\n\n- [Docker Compose](https://docs.docker.com/compose/): Docker Compose is a convenient Docker-based development environment which shares many features with Toast. However, it doesn't support defining tasks (like `lint`, `test`, `run`, etc.) or remote caching.\n- [Nix](https://nixos.org/nix/): Nix achieves reproducible builds by leveraging ideas from functional programming rather than containerization. We're big fans of Nix. However, Nix requires a larger commitment compared to Toast because you have to use the Nix package manager or write your own Nix derivations. For better or worse, Toast allows you to use familiar idioms like `apt-get install ...`.\n\nTo prevent Docker images from accumulating on your machine when using Docker-related tools such as Toast or Docker Compose, we recommend using [Docuum](https://github.com/stepchowfun/docuum) to perform least recently used (LRU) image eviction.\n\n## Tutorial\n\n### Defining a simple task\n\nLet's create a toastfile. Create a file named `toast.yml` with the following contents:\n\n```yaml\nimage: ubuntu\ntasks:\n  greet:\n    command: echo 'Hello, World!' # Toast will run this in a container.\n```\n\nNow run `toast`. You should see the following:\n\n![Defining a simple task.](https://raw.githubusercontent.com/stepchowfun/toast/main/media/simple-task-0.svg?sanitize=true)\n\nIf you run it again, Toast will find that nothing has changed and skip the task:\n\n![Caching.](https://raw.githubusercontent.com/stepchowfun/toast/main/media/caching-0.svg?sanitize=true)\n\nToast caches tasks to save you time. For example, you don't want to reinstall your dependencies every time you run your tests. However, caching may not be appropriate for some tasks, like running a development server. You can disable caching for a specific task and all tasks that depend on it with the `cache` option:\n\n```yaml\nimage: ubuntu\ntasks:\n  greet:\n    cache: false # Don't cache this task.\n    command: echo 'Hello, World!'\n```\n\n### Adding a dependency\n\nLet's make the greeting more fun with a program called `figlet`. We'll add a task to install `figlet`, and we'll change the `greet` task to depend on it:\n\n```yaml\nimage: ubuntu\ntasks:\n  install_figlet:\n    command: |\n      apt-get update\n      apt-get install --yes figlet\n\n  greet:\n    dependencies:\n      - install_figlet # Toast will run this task first.\n    command: figlet 'Hello, World!'\n```\n\nRun `toast` to see a marvelous greeting:\n\n![Adding a dependency.](https://raw.githubusercontent.com/stepchowfun/toast/main/media/dependencies-0.svg?sanitize=true)\n\n### Importing files from the host\n\nHere's a more realistic example. Suppose you want to compile and run a simple C program. Create a file called `main.c`:\n\n```c\n#include \u003cstdio.h\u003e\n\nint main(void) {\n  printf(\"Hello, World!\\n\");\n  return 0;\n}\n```\n\nUpdate `toast.yml` to compile and run the program:\n\n```yaml\nimage: ubuntu\ntasks:\n  install_gcc:\n    command: |\n      apt-get update\n      apt-get install --yes gcc\n\n  build:\n    dependencies:\n      - install_gcc\n    input_paths:\n      - main.c # Toast will copy this file into the container before running the command.\n    command: gcc main.c\n\n  run:\n    dependencies:\n      - build\n    command: ./a.out\n```\n\nNotice the `input_paths` array in the `build` task. Here we're copying a single file into the container, but we could instead import the entire directory containing the toastfile with `.`. By default, the files will be copied into a directory called `/scratch` in the container. The commands will be run in that directory as well.\n\nNow if you run `toast`, you'll see this:\n\n![Importing files from the host.](https://raw.githubusercontent.com/stepchowfun/toast/main/media/input-paths-0.svg?sanitize=true)\n\nFor subsequent runs, Toast will skip the task if nothing has changed. But if you update the greeting in `main.c`, Toast will detect the change and rerun the `build` and `run` tasks on the next invocation.\n\n### Exporting files from the container\n\nA common use case for Toast is to build a project. Naturally, you might wonder how to access the build artifacts produced inside the container from the host machine. It's easy to do with `output_paths`:\n\n```yaml\nimage: ubuntu\ntasks:\n  install_gcc:\n    command: |\n      apt-get update\n      apt-get install --yes gcc\n\n  build:\n    dependencies:\n      - install_gcc\n    input_paths:\n      - main.c\n    output_paths:\n      - a.out # Toast will copy this file onto the host after running the command.\n    command: gcc main.c\n```\n\nWhen Toast runs the `build` task, it will copy the `a.out` file to the host.\n\n![Exporting files from the container.](https://raw.githubusercontent.com/stepchowfun/toast/main/media/output-paths-0.svg?sanitize=true)\n\n### Passing arguments to a task\n\nSometimes it's useful for tasks to take arguments. For example, a `deploy` task might want to know whether you want to deploy to the `staging` or `production` cluster. To do this, add an `environment` section to your task:\n\n```yaml\nimage: ubuntu\ntasks:\n  deploy:\n    cache: false\n    environment:\n      CLUSTER: staging # Deploy to staging by default.\n    command: echo \"Deploying to $CLUSTER...\"\n```\n\nWhen you run this task, Toast will read the value from the environment:\n\n![Passing arguments to a task.](https://raw.githubusercontent.com/stepchowfun/toast/main/media/arguments-explicit-0.svg?sanitize=true)\n\nIf the variable doesn't exist in the environment, Toast will use the default value:\n\n![Using argument defaults.](https://raw.githubusercontent.com/stepchowfun/toast/main/media/arguments-default-0.svg?sanitize=true)\n\nIf you don't want to have a default, set it to `null`:\n\n```yaml\nimage: ubuntu\ntasks:\n  deploy:\n    cache: false\n    environment:\n      CLUSTER: null # No default; this variable must be provided at runtime.\n    command: echo \"Deploying to $CLUSTER...\"\n```\n\nNow if you run `toast deploy` without specifying a `CLUSTER`, Toast will complain about the missing variable and refuse to run the task.\n\nEnvironment variables listed in a task are also set for any tasks that run after it.\n\n### Running a server and mounting paths into the container\n\nToast can be used for more than just building a project. Suppose you're developing a website. You can define a Toast task to run your web server! Create a file called `index.html` with the following contents:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003ctitle\u003eWelcome to Toast!\u003c/title\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cp\u003eHello, World!\u003c/p\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\nWe can use a web server like [nginx](https://www.nginx.com/). The official `nginx` Docker image will do, but you could also use a more general image and define a Toast task to install nginx.\n\nIn our `toast.yml` file, we'll use the `ports` field to make the website accessible outside the container. We'll also use `mount_paths` rather than `input_paths` so we can edit the web page without having to restart the server.\n\n```yaml\nimage: nginx\ntasks:\n  serve:\n    cache: false # It doesn't make sense to cache this task.\n    mount_paths:\n      - index.html # Updates to this file will be visible inside the container.\n    ports:\n      - 3000:80 # Expose port 80 in the container as port 3000 on the host.\n    location: /usr/share/nginx/html/ # Nginx will serve the files in here.\n    command: nginx -g 'daemon off;' # Run in foreground mode.\n```\n\nNow you can use Toast to run the server:\n\n![Running a server.](https://raw.githubusercontent.com/stepchowfun/toast/main/media/server-1.svg?sanitize=true)\n\n### Configuring the shell\n\nIt's often desirable to configure the shell in some way before running any commands. Shells are typically configured with so-called \"startup files\" (e.g., `~/.bashrc`). However, many shells skip loading such configuration files when running in non-interactive, non-login mode, which is how the shell is invoked by Toast. Toast provides an alternative mechanism to configure the shell that doesn't require creating any special files or invoking the shell in a particular way.\n\nConsider the following toastfile which uses Bash as the shell, since that's the default preferred login shell in Ubuntu:\n\n```yaml\nimage: ubuntu\ntasks:\n  install_figlet:\n    command: |\n      apt-get update\n      apt-get install --yes figlet\n```\n\nWhat happens if `apt-get update` fails? Due to the way Bash works, the failure would be ignored and execution would continue to the subsequent line. You can fix this with `set -e` as follows:\n\n```yaml\nimage: ubuntu\ntasks:\n  install_figlet:\n    command: |\n      set -e # Make Bash fail fast.\n      apt-get update\n      apt-get install --yes figlet\n```\n\nHowever, it's tedious and error-prone to add that to each task separately. Instead, you can add it to every task at once by setting `command_prefix` as follows:\n\n```yaml\nimage: ubuntu\ncommand_prefix: set -e # Make Bash fail fast.\ntasks:\n  install_figlet:\n    command: |\n      apt-get update\n      apt-get install --yes figlet\n```\n\nFor Bash in particular, we recommend going even further and setting `set -euxo pipefail` instead of just `set -e`.\n\n### Dropping into an interactive shell\n\nIf you run Toast with `--shell`, Toast will drop you into an interactive shell inside the container when the requested tasks are finished, or if any of them fails. This feature is useful for debugging tasks or exploring what's in the container. Suppose you have the following toastfile:\n\n```yaml\nimage: ubuntu\ntasks:\n  install_figlet:\n    command: |\n      apt-get update\n      apt-get install --yes figlet\n```\n\nYou can run `toast --shell` to play with the `figlet` program:\n\n![Dropping into a shell.](https://raw.githubusercontent.com/stepchowfun/toast/main/media/shell-0.svg?sanitize=true)\n\nWhen you're done, the container is deleted automatically.\n\n## How Toast works\n\nGiven a set of tasks to run, Toast computes a [topological sort](https://en.wikipedia.org/wiki/Topological_sorting) of the dependency DAG to determine in what order to run the tasks. Toast then builds a Docker image for each task based on the image from the previous task in the topological sort, or the base image in the case of the first task.\n\nThe topological sort of an arbitrary DAG isn't necessarily unique. Toast uses an algorithm based on depth-first search, traversing children in lexicographical order. The algorithm is deterministic and invariant to the order in which tasks and dependencies are listed, so reordering tasks in a toastfile won't invalidate the cache. Furthermore, `toast foo bar` and `toast bar foo` are guaranteed to produce identical schedules to maximize cache utilization.\n\nFor each task in the schedule, Toast first computes a cache key based on a hash of the shell command, the contents of the `input_paths`, the cache key of the previous task in the schedule, etc. Toast will then look for a Docker image tagged with that cache key. If the image is found, Toast will skip the task. Otherwise, Toast will create a container, copy any `input_paths` into it, run the shell command, copy any `output_paths` from the container to the host, commit the container to an image, and delete the container. The image is tagged with the cache key so the task can be skipped for subsequent runs.\n\nToast aims to make as few assumptions about the container environment as possible. Toast only assumes there is a program at `/bin/su` which can be invoked as `su -c COMMAND USER`. This program is used to run commands for tasks in the container as the appropriate user with their preferred shell. Every popular Linux distribution has a `su` utility that supports this usage. Toast has integration tests to ensure it works with popular base images such as `debian`, `alpine`, `busybox`, etc.\n\n## Toastfile reference\n\nA *toastfile* is a YAML file (typically named `toast.yml`) that defines tasks and their dependencies. The schema contains the following top-level keys and defaults:\n\n```yaml\nimage: \u003crequired\u003e   # Docker image name with optional tag or digest\ndefault: null       # Name of default task to run or `null` to run all tasks by default\nlocation: /scratch  # Path in the container for running tasks\nuser: root          # Name of the user in the container for running tasks\ncommand_prefix: ''  # A string to be prepended to all commands by default\ntasks: {}           # Map from task name to task\n```\n\nTasks have the following schema and defaults:\n\n```yaml\ndescription: null           # A description of the task for the `--list` option\ndependencies: []            # Names of dependencies\ncache: true                 # Whether a task can be cached\nenvironment: {}             # Map from environment variable to optional default\ninput_paths: []             # Paths to copy into the container\nexcluded_input_paths: []    # A denylist for `input_paths`\noutput_paths: []            # Paths to copy out of the container if the task succeeds\noutput_paths_on_failure: [] # Paths to copy out of the container if the task fails\nmount_paths: []             # Paths to mount into the container\nmount_readonly: false       # Whether to mount the `mount_paths` as readonly\nports: []                   # Port mappings to publish\nlocation: null              # Overrides the corresponding top-level value\nuser: null                  # Overrides the corresponding top-level value\ncommand: ''                 # Shell command to run in the container\ncommand_prefix: null        # Overrides the corresponding top-level value\nextra_docker_arguments: []  # Additional arguments for `docker container create`\n```\n\nThe [toastfile](https://github.com/stepchowfun/toast/blob/main/toast.yml) for Toast itself is a comprehensive real-world example.\n\n## Configuration\n\nToast can be customized with a YAML configuration file. The default location of the configuration file depends on the operating system:\n\n- For macOS, the default location is `$HOME/Library/Application Support/toast/toast.yml`.\n- For other Unix platforms, Toast follows the [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html). The default location is `$XDG_CONFIG_HOME/toast/toast.yml` or `$HOME/.config/toast/toast.yml` if `XDG_CONFIG_HOME` isn't set to an absolute path.\n- For Windows, the default location is `{FOLDERID_RoamingAppData}\\toast\\toast.yml`.\n\nThe schema of the configuration file is described in the subsections below.\n\n### Cache configuration\n\nToast supports local and remote caching. By default, only local caching is enabled. Remote caching requires that the Docker Engine is logged into a Docker registry (e.g., via `docker login`).\n\nThe cache-related fields and their default values are as follows:\n\n```yaml\ndocker_repo: toast        # Docker repository\nread_local_cache: true    # Whether Toast should read from local cache\nwrite_local_cache: true   # Whether Toast should write to local cache\nread_remote_cache: false  # Whether Toast should read from remote cache\nwrite_remote_cache: false # Whether Toast should write to remote cache\n```\n\nEach of these options can be overridden via command-line options (see [below](#command-line-options)).\n\nA typical configuration for a CI environment will enable all forms of caching, whereas for local development you may want to set `write_remote_cache: false` to avoid waiting for remote cache writes.\n\n### Docker CLI\n\nYou can configure the Docker CLI binary used by Toast. Toast uses the `PATH` environment variable to search for the specified binary. You can use this mechanism to switch to a drop-in replacement for the Docker CLI, such as Podman.\n\nThe relevant field and its default value are as follows:\n\n```yaml\ndocker_cli: docker\n```\n\n## Command-line options\n\nBy default, Toast looks for a toastfile called `toast.yml` in the working directory, then in the parent directory, and so on. Any paths in the toastfile are relative to where the toastfile lives, not the working directory. This means you can run Toast from anywhere in your project and get the same results.\n\nRun `toast` with no arguments to execute the default task, or all the tasks if the toastfile doesn't define a default. You can also execute specific tasks and their dependencies:\n\n```sh\ntoast task1 task2 task3…\n```\n\nHere are all the supported command-line options:\n\n```\nUSAGE:\n    toast [OPTIONS] [--] [TASKS]...\n\nOPTIONS:\n    -c, --config-file \u003cPATH\u003e\n            Sets the path of the config file\n\n        --docker-cli \u003cCLI\u003e\n            Sets the Docker CLI binary\n\n    -r, --docker-repo \u003cREPO\u003e\n            Sets the Docker repository for remote caching\n\n    -f, --file \u003cPATH\u003e\n            Sets the path to the toastfile\n\n        --force \u003cTASK\u003e...\n            Runs a task unconditionally, even if it’s cached\n\n        --force-all\n            Pulls the base image and runs all tasks unconditionally\n\n    -h, --help\n            Prints help information\n\n    -l, --list\n            Lists the tasks that have a description\n\n    -o, --output-dir \u003cPATH\u003e\n            Sets the output directory\n\n        --read-local-cache \u003cBOOL\u003e\n            Sets whether local cache reading is enabled\n\n        --read-remote-cache \u003cBOOL\u003e\n            Sets whether remote cache reading is enabled\n\n    -s, --shell\n            Drops you into a containerized shell after the tasks are finished\n\n    -v, --version\n            Prints version information\n\n        --write-local-cache \u003cBOOL\u003e\n            Sets whether local cache writing is enabled\n\n        --write-remote-cache \u003cBOOL\u003e\n            Sets whether remote cache writing is enabled\n\n\nARGS:\n    \u003cTASKS\u003e...\n            Sets the tasks to run\n```\n\n## Installation instructions\n\n### Installation on macOS or Linux (AArch64 or x86-64)\n\nIf you're running macOS or Linux (AArch64 or x86-64), you can install Toast with this command:\n\n\n```sh\ncurl https://raw.githubusercontent.com/stepchowfun/toast/main/install.sh -LSfs | sh\n```\n\nThe same command can be used again to update to the latest version.\n\nThe installation script supports the following optional environment variables:\n\n- `VERSION=x.y.z` (defaults to the latest version)\n- `PREFIX=/path/to/install` (defaults to `/usr/local/bin`)\n\nFor example, the following will install Toast into the working directory:\n\n```sh\ncurl https://raw.githubusercontent.com/stepchowfun/toast/main/install.sh -LSfs | PREFIX=. sh\n```\n\nIf you prefer not to use this installation method, you can download the binary from the [releases page](https://github.com/stepchowfun/toast/releases), make it executable (e.g., with `chmod`), and place it in some directory in your [`PATH`](https://en.wikipedia.org/wiki/PATH_\\(variable\\)) (e.g., `/usr/local/bin`).\n\n### Installation on Windows (AArch64 or x86-64)\n\nIf you're running Windows (AArch64 or x86-64), download the latest binary from the [releases page](https://github.com/stepchowfun/toast/releases) and rename it to `toast` (or `toast.exe` if you have file extensions visible). Create a directory called `Toast` in your `%PROGRAMFILES%` directory (e.g., `C:\\Program Files\\Toast`), and place the renamed binary in there. Then, in the \"Advanced\" tab of the \"System Properties\" section of Control Panel, click on \"Environment Variables...\" and add the full path to the new `Toast` directory to the `PATH` variable under \"System variables\". Note that the `Program Files` directory might have a different name if Windows is configured for a language other than English.\n\nTo update an existing installation, simply replace the existing binary.\n\n\n### Installation with Homebrew\n\nIf you have [Homebrew](https://brew.sh/), you can install Toast as follows:\n\n```sh\nbrew install toast\n```\n\nYou can update an existing installation with `brew upgrade toast`.\n\n### Installation with MacPorts\n\nOn macOS, you can also install Toast via [MacPorts](https://www.macports.org) as follows:\n\n```sh\nsudo port install toast\n```\n\nYou can update an existing installation via:\n\n```sh\nsudo port selfupdate\nsudo port upgrade toast\n```\n\n### Installation with Cargo\n\nIf you have [Cargo](https://doc.rust-lang.org/cargo/), you can install Toast as follows:\n\n```sh\ncargo install toast\n```\n\nYou can run that command with `--force` to update an existing installation.\n\n## Running Toast in CI\n\nThe easiest way to run Toast in CI is to use [GitHub Actions](https://help.github.com/en/actions). Toast provides a convenient GitHub action that you can use in your [workflows](https://help.github.com/en/actions/configuring-and-managing-workflows/configuring-and-managing-workflow-files-and-runs). Here's a simple workflow that runs Toast with no arguments:\n\n```yaml\n# .github/workflows/ci.yml\nname: Continuous integration\non:\n  pull_request:\n  push:\n    branches:\n    - main\njobs:\n  ci:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v4\n    - uses: stepchowfun/toast/.github/actions/toast@main\n```\n\nHere's a more customized workflow that showcases all the options:\n\n```yaml\n# .github/workflows/ci.yml\nname: Continuous integration\non:\n  pull_request:\n  push:\n    branches:\n    - main\njobs:\n  ci:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v4\n    - if: github.event_name == 'push'\n      uses: docker/login-action@v3\n      with:\n        username: DOCKER_USERNAME\n        password: ${{ secrets.DOCKER_PASSWORD }}\n    - uses: stepchowfun/toast/.github/actions/toast@main\n      with:\n        file: toastfiles/toast.yml\n        tasks: build lint test\n        docker_repo: DOCKER_USERNAME/DOCKER_REPO\n        read_remote_cache: true\n        write_remote_cache: ${{ github.event_name == 'push' }}\n```\n\n## Requirements\n\n- Toast requires [Docker Engine](https://www.docker.com/products/docker-engine) 17.06.0 or later.\n- Toast only works with Linux containers; Windows containers aren't currently supported. However, in addition to Linux hosts, Toast also supports macOS and Windows hosts with the appropriate virtualization capabilities thanks to [Docker Desktop](https://www.docker.com/products/docker-desktop).\n\n## Acknowledgements\n\nToast was inspired by an in-house tool used at Airbnb for CI jobs. The design was heavily influenced by the lessons I learned working on that tool and building out Airbnb's CI system with the fabulous CI Infrastructure Team.\n\nSpecial thanks to Julia Wang ([@juliahw](https://github.com/juliahw)) for valuable early feedback. Thanks to her and Mark Tai ([@marktai](https://github.com/marktai)) for coming up with the name *Toast*.\n\nThe terminal animations were produced with [asciinema](https://asciinema.org/) and [svg-term-cli](https://github.com/marionebl/svg-term-cli).\n","funding_links":["https://github.com/sponsors/stepchowfun"],"categories":["Rust","Command Line","docker","命令行工具"],"sub_categories":["Dependency Management"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstepchowfun%2Ftoast","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstepchowfun%2Ftoast","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstepchowfun%2Ftoast/lists"}