Dagger 0.6: New Terminal UI

May 25, 2023

Alex Suracci

Share
Share
Share
Share

Dagger 0.6 updates the dagger run CLI command, which you can now use to run your Dagger code with a shiny new terminal UI (TUI):

Why?

Dagger works by building up a DAG of operations and evaluating them, often in parallel. By nature, this is a difficult thing to display in the terminal. It's easy to show the output of one operation at a time, but as soon as you have parallelism you'll get jumbled output that's hard to grok.

The current LogOutput format solves this by alternating between active operations and showing chunks of output at a time. It will print a header showing the output source and then print its output, with a small cooldown that allows it to get "bored" and swap to another active operation.

For example, here's how node ./build.js currently looks for the Node.js services example:

Connected to engine c1b34068aa26
#1 resolve image config for docker.io/library/postgres:15.2
#1 DONE 1.2s

#2 resolve image config for docker.io/library/node:16
#2 DONE 0.3s

#3 service 85BR3ID518VOQ
#3 resolve docker.io/library/postgres:15.2@sha256:78a275d4c891f7b3a33d3f1a78eda9f1d744954d9e20122bfdc97cdda25cddaf done
#3 0.211 The files belonging to this database system will be owned by user "postgres".
<snipped>
#3 1.568 2023-05-18 18:18:14.071 UTC [15] LOG:  database system is ready to accept connections
#3 ...

#5 from node:16
#5 resolve docker.io/library/node:16@sha256:550f484fc5f314b575f5e397c9e2c71d7f218e59729fcda9ffa7ea1fc825dce7 0.0s done
#5 CACHED

#6 
#6 DONE 0.0s

#6 
#6 4.953 
#6 4.953 added 341 packages, and audited 342 packages in 5s
<snipped>
#6 DONE 5.2s

#3 service 85BR3ID518VOQ
#3 ...

#6 
#6 0.531 
<snipped>
#6 1.556 Ran all test suites.
#6 DONE 7.0s

#3 service 85BR3ID518VOQ
#3 CANCELED

This format is much better than directly printing output in parallel, because you can at least see which operation is producing each chunk of output.

When multiple commands are actively printing output, however, it becomes more difficult to follow. It can either stick to one command for too long, not showing the concurrent output at all, or hop back and forth between them with a lot of extra noise from the headers in the output. This output format comes directly from Buildkit's plaintext console renderer, which also limits what we can show to the user: only things that go through Buildkit's Solve() call.

But the biggest problem with the LogOutput format is that it's not very pretty. Using Dagger should spark joy. If users are going to be running CI/CD builds all day, it needs to be easy on the eyes!

Enter the new terminal UI

The new terminal UI is implemented with a new progress toolkit that we can use to display anything we want: service health-checks, GraphQL API calls, debug logs, etc. It shows a full-blown DAG in a style similar to git log --graph, with the current state of your DAG's evaluation and a full snapshot of all output at the end.

This new terminal UI is designed for rapid iteration, in the same way regular scripting works: you run a command, it shows live progress, and then leaves all the output in your terminal scrollback. You've already seen it at the top of this post, but here it is again:

There's a lot of information being conveyed in this UI, so here's a quick primer:

  • Parallel pipelines are represented by vertical columns (┃ for active, │ for inactive).

  • Operations within a pipeline are represented by block characters (█).

  • Sub-tasks of an operation are listed beneath it (┣).

  • Actively running operations blink until they finish (█▓▒░█▓▒░).

  • Each pipeline forks from its parent pipeline and show its name in bold after a caret (▼).

  • Dependencies across pipelines are shown as a column that forks beneath the output operation and connects to each input, with the name of the output in grey (pull docker.io/library/node:16).

  • Actively running operations are always shown at the bottom of the screen.

  • Failed operations are also always shown at the bottom of the screen.

It's a lot to take in, and you're not meant to digest it all the time. The idea is for it to act as passive feedback as you refactor your DAG. If you don't care about every single detail, you can just keep your eyes on the bottom of the screen to see anything important.

Debugging

With dagger run --debug, you can see all of the underlying GraphQL API calls. This reveals what's actually happening if things appear to pause for a moment, as with the import() API call in the demo below.

<TUI DEBUG VIDEO GOES HERE - IT'S TOO BIG FOR THE FREE PLAN>

Admittedly, the output appears pretty cluttered owing to the small screen size. We expect to fine-tune things some more in the future!

The "other" terminal UI

Astute observers may have noticed this looks nothing like the terminal UI demonstrated in previous community calls.

This "other" UI is called the interactive, or tree-style, TUI. The interactive TUI is still available for the moment while we experiment. You can enable it by setting the _EXPERIMENTAL_DAGGER_INTERACTIVE_TUI environment variable. Here's what it looks like:

After asking the community, we decided not to make this one the default. The interactive tree-style UI is better for interactive debugging as opposed to rapid iteration.

SDK Updates

We've also released new versions of our SDKs with various SDK-specific bug fixes and improvements.

For a complete list of improvements, refer to the changelog for each SDK:

New Dagger Cookbook and Documentation

We've been continuously improving and adding to our documentation. Here are a few highlights:

Have comments on the new terminal UI? An interesting recipe to add to our cookbook? An idea for new documentation? Let us know in Discord or create a GitHub issue.

Dagger 0.6 updates the dagger run CLI command, which you can now use to run your Dagger code with a shiny new terminal UI (TUI):

Why?

Dagger works by building up a DAG of operations and evaluating them, often in parallel. By nature, this is a difficult thing to display in the terminal. It's easy to show the output of one operation at a time, but as soon as you have parallelism you'll get jumbled output that's hard to grok.

The current LogOutput format solves this by alternating between active operations and showing chunks of output at a time. It will print a header showing the output source and then print its output, with a small cooldown that allows it to get "bored" and swap to another active operation.

For example, here's how node ./build.js currently looks for the Node.js services example:

Connected to engine c1b34068aa26
#1 resolve image config for docker.io/library/postgres:15.2
#1 DONE 1.2s

#2 resolve image config for docker.io/library/node:16
#2 DONE 0.3s

#3 service 85BR3ID518VOQ
#3 resolve docker.io/library/postgres:15.2@sha256:78a275d4c891f7b3a33d3f1a78eda9f1d744954d9e20122bfdc97cdda25cddaf done
#3 0.211 The files belonging to this database system will be owned by user "postgres".
<snipped>
#3 1.568 2023-05-18 18:18:14.071 UTC [15] LOG:  database system is ready to accept connections
#3 ...

#5 from node:16
#5 resolve docker.io/library/node:16@sha256:550f484fc5f314b575f5e397c9e2c71d7f218e59729fcda9ffa7ea1fc825dce7 0.0s done
#5 CACHED

#6 
#6 DONE 0.0s

#6 
#6 4.953 
#6 4.953 added 341 packages, and audited 342 packages in 5s
<snipped>
#6 DONE 5.2s

#3 service 85BR3ID518VOQ
#3 ...

#6 
#6 0.531 
<snipped>
#6 1.556 Ran all test suites.
#6 DONE 7.0s

#3 service 85BR3ID518VOQ
#3 CANCELED

This format is much better than directly printing output in parallel, because you can at least see which operation is producing each chunk of output.

When multiple commands are actively printing output, however, it becomes more difficult to follow. It can either stick to one command for too long, not showing the concurrent output at all, or hop back and forth between them with a lot of extra noise from the headers in the output. This output format comes directly from Buildkit's plaintext console renderer, which also limits what we can show to the user: only things that go through Buildkit's Solve() call.

But the biggest problem with the LogOutput format is that it's not very pretty. Using Dagger should spark joy. If users are going to be running CI/CD builds all day, it needs to be easy on the eyes!

Enter the new terminal UI

The new terminal UI is implemented with a new progress toolkit that we can use to display anything we want: service health-checks, GraphQL API calls, debug logs, etc. It shows a full-blown DAG in a style similar to git log --graph, with the current state of your DAG's evaluation and a full snapshot of all output at the end.

This new terminal UI is designed for rapid iteration, in the same way regular scripting works: you run a command, it shows live progress, and then leaves all the output in your terminal scrollback. You've already seen it at the top of this post, but here it is again:

There's a lot of information being conveyed in this UI, so here's a quick primer:

  • Parallel pipelines are represented by vertical columns (┃ for active, │ for inactive).

  • Operations within a pipeline are represented by block characters (█).

  • Sub-tasks of an operation are listed beneath it (┣).

  • Actively running operations blink until they finish (█▓▒░█▓▒░).

  • Each pipeline forks from its parent pipeline and show its name in bold after a caret (▼).

  • Dependencies across pipelines are shown as a column that forks beneath the output operation and connects to each input, with the name of the output in grey (pull docker.io/library/node:16).

  • Actively running operations are always shown at the bottom of the screen.

  • Failed operations are also always shown at the bottom of the screen.

It's a lot to take in, and you're not meant to digest it all the time. The idea is for it to act as passive feedback as you refactor your DAG. If you don't care about every single detail, you can just keep your eyes on the bottom of the screen to see anything important.

Debugging

With dagger run --debug, you can see all of the underlying GraphQL API calls. This reveals what's actually happening if things appear to pause for a moment, as with the import() API call in the demo below.

<TUI DEBUG VIDEO GOES HERE - IT'S TOO BIG FOR THE FREE PLAN>

Admittedly, the output appears pretty cluttered owing to the small screen size. We expect to fine-tune things some more in the future!

The "other" terminal UI

Astute observers may have noticed this looks nothing like the terminal UI demonstrated in previous community calls.

This "other" UI is called the interactive, or tree-style, TUI. The interactive TUI is still available for the moment while we experiment. You can enable it by setting the _EXPERIMENTAL_DAGGER_INTERACTIVE_TUI environment variable. Here's what it looks like:

After asking the community, we decided not to make this one the default. The interactive tree-style UI is better for interactive debugging as opposed to rapid iteration.

SDK Updates

We've also released new versions of our SDKs with various SDK-specific bug fixes and improvements.

For a complete list of improvements, refer to the changelog for each SDK:

New Dagger Cookbook and Documentation

We've been continuously improving and adding to our documentation. Here are a few highlights:

Have comments on the new terminal UI? An interesting recipe to add to our cookbook? An idea for new documentation? Let us know in Discord or create a GitHub issue.

Dagger 0.6 updates the dagger run CLI command, which you can now use to run your Dagger code with a shiny new terminal UI (TUI):

Why?

Dagger works by building up a DAG of operations and evaluating them, often in parallel. By nature, this is a difficult thing to display in the terminal. It's easy to show the output of one operation at a time, but as soon as you have parallelism you'll get jumbled output that's hard to grok.

The current LogOutput format solves this by alternating between active operations and showing chunks of output at a time. It will print a header showing the output source and then print its output, with a small cooldown that allows it to get "bored" and swap to another active operation.

For example, here's how node ./build.js currently looks for the Node.js services example:

Connected to engine c1b34068aa26
#1 resolve image config for docker.io/library/postgres:15.2
#1 DONE 1.2s

#2 resolve image config for docker.io/library/node:16
#2 DONE 0.3s

#3 service 85BR3ID518VOQ
#3 resolve docker.io/library/postgres:15.2@sha256:78a275d4c891f7b3a33d3f1a78eda9f1d744954d9e20122bfdc97cdda25cddaf done
#3 0.211 The files belonging to this database system will be owned by user "postgres".
<snipped>
#3 1.568 2023-05-18 18:18:14.071 UTC [15] LOG:  database system is ready to accept connections
#3 ...

#5 from node:16
#5 resolve docker.io/library/node:16@sha256:550f484fc5f314b575f5e397c9e2c71d7f218e59729fcda9ffa7ea1fc825dce7 0.0s done
#5 CACHED

#6 
#6 DONE 0.0s

#6 
#6 4.953 
#6 4.953 added 341 packages, and audited 342 packages in 5s
<snipped>
#6 DONE 5.2s

#3 service 85BR3ID518VOQ
#3 ...

#6 
#6 0.531 
<snipped>
#6 1.556 Ran all test suites.
#6 DONE 7.0s

#3 service 85BR3ID518VOQ
#3 CANCELED

This format is much better than directly printing output in parallel, because you can at least see which operation is producing each chunk of output.

When multiple commands are actively printing output, however, it becomes more difficult to follow. It can either stick to one command for too long, not showing the concurrent output at all, or hop back and forth between them with a lot of extra noise from the headers in the output. This output format comes directly from Buildkit's plaintext console renderer, which also limits what we can show to the user: only things that go through Buildkit's Solve() call.

But the biggest problem with the LogOutput format is that it's not very pretty. Using Dagger should spark joy. If users are going to be running CI/CD builds all day, it needs to be easy on the eyes!

Enter the new terminal UI

The new terminal UI is implemented with a new progress toolkit that we can use to display anything we want: service health-checks, GraphQL API calls, debug logs, etc. It shows a full-blown DAG in a style similar to git log --graph, with the current state of your DAG's evaluation and a full snapshot of all output at the end.

This new terminal UI is designed for rapid iteration, in the same way regular scripting works: you run a command, it shows live progress, and then leaves all the output in your terminal scrollback. You've already seen it at the top of this post, but here it is again:

There's a lot of information being conveyed in this UI, so here's a quick primer:

  • Parallel pipelines are represented by vertical columns (┃ for active, │ for inactive).

  • Operations within a pipeline are represented by block characters (█).

  • Sub-tasks of an operation are listed beneath it (┣).

  • Actively running operations blink until they finish (█▓▒░█▓▒░).

  • Each pipeline forks from its parent pipeline and show its name in bold after a caret (▼).

  • Dependencies across pipelines are shown as a column that forks beneath the output operation and connects to each input, with the name of the output in grey (pull docker.io/library/node:16).

  • Actively running operations are always shown at the bottom of the screen.

  • Failed operations are also always shown at the bottom of the screen.

It's a lot to take in, and you're not meant to digest it all the time. The idea is for it to act as passive feedback as you refactor your DAG. If you don't care about every single detail, you can just keep your eyes on the bottom of the screen to see anything important.

Debugging

With dagger run --debug, you can see all of the underlying GraphQL API calls. This reveals what's actually happening if things appear to pause for a moment, as with the import() API call in the demo below.

<TUI DEBUG VIDEO GOES HERE - IT'S TOO BIG FOR THE FREE PLAN>

Admittedly, the output appears pretty cluttered owing to the small screen size. We expect to fine-tune things some more in the future!

The "other" terminal UI

Astute observers may have noticed this looks nothing like the terminal UI demonstrated in previous community calls.

This "other" UI is called the interactive, or tree-style, TUI. The interactive TUI is still available for the moment while we experiment. You can enable it by setting the _EXPERIMENTAL_DAGGER_INTERACTIVE_TUI environment variable. Here's what it looks like:

After asking the community, we decided not to make this one the default. The interactive tree-style UI is better for interactive debugging as opposed to rapid iteration.

SDK Updates

We've also released new versions of our SDKs with various SDK-specific bug fixes and improvements.

For a complete list of improvements, refer to the changelog for each SDK:

New Dagger Cookbook and Documentation

We've been continuously improving and adding to our documentation. Here are a few highlights:

Have comments on the new terminal UI? An interesting recipe to add to our cookbook? An idea for new documentation? Let us know in Discord or create a GitHub issue.

Get Involved With the community

Discover what our community is doing, and join the conversation on Discord & GitHub to help shape the evolution of Dagger.

Subscribe to our newsletter

Get Involved With the community

Discover what our community is doing, and join the conversation on Discord & GitHub to help shape the evolution of Dagger.

Subscribe to our newsletter

Get Involved With the community

Discover what our community is doing, and join the conversation on Discord & GitHub to help shape the evolution of Dagger.

Subscribe to our newsletter