Skip to content

Commit

Permalink
fix: edge cases for running interactive goal commands with --tty flag (
Browse files Browse the repository at this point in the history
  • Loading branch information
aorumbayev authored Oct 29, 2024
1 parent 1394416 commit e280a7f
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 12 deletions.
5 changes: 5 additions & 0 deletions docs/cli/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
- [goal](#goal)
- [Options](#options-11)
- [--console](#--console)
- [--interactive](#--interactive)
- [Arguments](#arguments-6)
- [GOAL_ARGS](#goal_args)
- [init](#init)
Expand Down Expand Up @@ -591,6 +592,10 @@ algokit goal [OPTIONS] [GOAL_ARGS]...
### --console
Open a Bash console so you can execute multiple goal commands and/or interact with a filesystem.


### --interactive
Force running the goal command in interactive mode.

### Arguments


Expand Down
23 changes: 22 additions & 1 deletion docs/features/goal.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,19 @@ $ ~ algokit goal
```

## Working with Files in the Container

When interacting with the container, especially if you're using tools like goal, you might need to reference files or directories. Here's how to efficiently deal with files and directories:

### Automatic File Mounting

When you specify a file or directory path in your `goal` command, the system will automatically mount that path from your local filesystem into the container. This way, you don't need to copy files manually each time.

For instance, if you want to compile a `teal` file:

```
algokit goal clerk compile /Path/to/inputfile/approval.teal -o /Path/to/outputfile/approval.compiled
```

Here, `/Path/to/inputfile/approval.teal` and `/Path/to/outputfile/approval.compiled` are paths on your local file system, and they will be automatically accessible to the `goal` command inside the container.

### Manual Copying of Files
Expand All @@ -98,6 +101,7 @@ In case you want to manually copy files into the container, you can do so using
```
docker cp foo.txt algokit_algod:/root
```

This command copies the `foo.txt` from your local system into the root directory of the `algokit_algod` container.

Note: Manual copying is optional and generally only necessary if you have specific reasons for doing so since the system will auto-mount paths specified in commands.
Expand All @@ -106,7 +110,7 @@ Note: Manual copying is optional and generally only necessary if you have specif

If you want to run multiple commands or interact with the filesystem you can execute `algokit goal --console`. This will open a [Bash](https://www.gnu.org/software/bash/) shell session on the `algod` Docker container and from there you can execute goal directly, e.g.:

```
```bash
$ algokit goal --console
Opening Bash console on the algod node; execute `exit` to return to original console
root@82d41336608a:~# goal account list
Expand All @@ -115,4 +119,21 @@ root@82d41336608a:~# goal account list
[online] 4BH5IKMDDHEJEOZ7T5LLT4I7EVIH5XCOTX3TPVQB3HY5TUBVT4MYXJOZVA 4BH5IKMDDHEJEOZ7T5LLT4I7EVIH5XCOTX3TPVQB3HY5TUBVT4MYXJOZVA 2000000000000000 microAlgos
```

## Interactive Mode

Some `goal` commands require interactive input from the user. By default, AlgoKit will attempt to run commands in non-interactive mode first, and automatically switch to interactive mode if needed. You can force a command to run in interactive mode by using the `--interactive` flag:

```bash
$ algokit goal --interactive wallet new algodev
Please choose a password for wallet 'algodev':
Please confirm the password:
Creating wallet...
Created wallet 'algodev'
Your new wallet has a backup phrase that can be used for recovery.
Keeping this backup phrase safe is extremely important.
Would you like to see it now? (Y/n): n
```

This is particularly useful when you know a command will require user input, such as creating new accounts, importing keys, or signing transactions.

For more details about the `AlgoKit goal` command, please refer to the [AlgoKit CLI reference documentation](../cli/index.md#goal).
33 changes: 25 additions & 8 deletions src/algokit/cli/goal.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,14 @@
help="Open a Bash console so you can execute multiple goal commands and/or interact with a filesystem.",
default=False,
)
@click.option(
"--interactive",
is_flag=True,
help="Force running the goal command in interactive mode.",
default=False,
)
@click.argument("goal_args", nargs=-1, type=click.UNPROCESSED)
def goal_command(*, console: bool, goal_args: list[str]) -> None:
def goal_command(*, console: bool, interactive: bool, goal_args: list[str]) -> None: # noqa: C901, PLR0912
"""
Run the Algorand goal CLI against the AlgoKit LocalNet.
Expand Down Expand Up @@ -80,17 +86,28 @@ def goal_command(*, console: bool, goal_args: list[str]) -> None:
logger.info("Opening Bash console on the algod node; execute `exit` to return to original console")
result = proc.run_interactive(f"{container_engine} exec -it -w /root algokit_{sandbox.name}_algod bash".split())
else:
cmd = f"{container_engine} exec --interactive --workdir /root algokit_{sandbox.name}_algod goal".split()
cmd = f"{container_engine} exec {'--tty' if interactive else ''} --interactive --workdir /root algokit_{sandbox.name}_algod goal".split() # noqa: E501
input_files, output_files, goal_args = preprocess_command_args(
goal_args, volume_mount_path_local, volume_mount_path_docker
)
cmd = cmd + goal_args
result = proc.run(
cmd,
stdout_log_level=logging.INFO,
prefix_process=False,
pass_stdin=True,
)

if interactive:
result = proc.run_interactive(cmd)
else:
# Try non-interactive first, fallback to interactive if it fails with input-related error
result = proc.run(
cmd,
stdout_log_level=logging.INFO,
prefix_process=False,
pass_stdin=True,
)
if result.exit_code != 0 and "inappropriate ioctl" in (result.output or ""):
# Fallback to interactive mode if we detect TTY-related errors
logger.debug("Command failed with TTY error, retrying in interactive mode")
cmd.insert(2, "--tty")
result = proc.run_interactive(cmd)

post_process(input_files, output_files, volume_mount_path_local)

if result.exit_code != 0:
Expand Down
7 changes: 4 additions & 3 deletions tests/goal/test_goal.test_goal_help.approved.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Usage: algokit goal [OPTIONS] [GOAL_ARGS]...
information.

Options:
--console Open a Bash console so you can execute multiple goal commands
and/or interact with a filesystem.
-h, --help Show this message and exit.
--console Open a Bash console so you can execute multiple goal commands
and/or interact with a filesystem.
--interactive Force running the goal command in interactive mode.
-h, --help Show this message and exit.

1 comment on commit e280a7f

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Coverage Report
FileStmtsMissCoverMissing
src/algokit
   __init__.py15753%6–13, 17–24, 32–34
   __main__.py440%1–7
src/algokit/cli
   __init__.py47394%31–34
   codespace.py50982%28, 114, 137, 150–155
   completions.py108992%63–64, 83, 93–99
   dispenser.py121199%77
   doctor.py53394%146–148
   explore.py631576%35–40, 42–47, 85–92, 113
   generate.py70396%76–77, 155
   goal.py54591%85, 96, 107–109
   init.py3102492%491–492, 497–498, 501, 522, 525–527, 538, 542, 600, 626, 655, 688, 697–699, 702–707, 720, 739, 751–752
   localnet.py1643280%67, 88–115, 164–168, 212, 233, 248–258, 271, 322, 343–344
   task.py34391%25–28
src/algokit/cli/common
   utils.py37295%137, 139
src/algokit/cli/project
   bootstrap.py32197%33
   deploy.py1172083%47, 49, 102, 125, 147–149, 270, 277, 291–299, 302–311
   link.py891682%60, 65–66, 101–105, 115–120, 148–149, 218–219, 223
   list.py33585%21–23, 51–56
   run.py46296%38, 174
src/algokit/cli/tasks
   analyze.py81199%81
   assets.py821384%65–66, 72, 74–75, 105, 119, 125–126, 132, 134, 136–137
   ipfs.py51884%52, 80, 92, 94–95, 105–107
   mint.py1061586%51, 73, 100–103, 108, 113, 131–132, 158, 335–339
   send_transaction.py651085%52–53, 57, 89, 158, 170–174
   sign_transaction.py59886%21, 28–30, 71–72, 109, 123
   transfer.py39392%26, 90, 117
   utils.py1144660%29–37, 43–46, 78–79, 103–104, 128–136, 155–165, 212, 261–262, 282–293, 300–302, 324
   vanity_address.py561082%41, 45–48, 112, 114, 121–123
   wallet.py79495%21, 66, 136, 162
src/algokit/core
   codespace.py1756861%34–37, 41–44, 48–71, 111–112, 125–133, 191, 200–202, 210, 216–217, 229–236, 251–298, 311–313, 338–344, 348, 395
   conf.py57984%12, 24, 28, 36, 38, 73–75, 80
   dispenser.py2022687%92, 124–125, 142–150, 192–193, 199–201, 219–220, 260–261, 319, 333–335, 346–347, 357, 370, 385
   doctor.py65789%67–69, 92–94, 134
   generate.py50394%44, 85, 103
   goal.py65494%21, 36–37, 47
   init.py671085%53, 57–62, 70, 81, 88, 108–109
   log_handlers.py68790%50–51, 63, 112–116, 125
   proc.py45198%99
   sandbox.py2762392%32, 89–92, 97, 101–103, 174, 222–229, 240, 611, 627, 652, 660
   typed_client_generation.py1702088%62–64, 103–108, 132, 135–138, 156, 159–162, 229, 232–235
   utils.py1504073%50–51, 57–69, 125–131, 155, 158, 164–177, 206–208, 237–240, 262
src/algokit/core/_vendor/auth0/authentication
   token_verifier.py15711129%16, 45, 58, 73–85, 98–107, 119–124, 136–137, 140, 170, 178–180, 190–199, 206–213, 227–236, 258, 280–287, 314–323, 333–444
src/algokit/core/compilers
   python.py28582%19–20, 25, 49–50
src/algokit/core/config_commands
   container_engine.py412149%24, 29–31, 47–76
   version_prompt.py921485%37–38, 68, 87–90, 108, 118–125, 148
src/algokit/core/project
   __init__.py53394%50, 86, 145
   bootstrap.py120893%47, 126–127, 149, 176, 207–209
   deploy.py69987%108–111, 120–122, 126, 131
   run.py1321390%83, 88, 97–98, 133–134, 138–139, 143, 147, 277–278, 293
src/algokit/core/tasks
   analyze.py93397%105–112, 187
   ipfs.py63789%58–64, 140, 144, 146, 152
   nfd.py491373%25, 31, 34–41, 70–72, 99–101
   vanity_address.py903462%49–50, 54, 59–75, 92–108, 128–131
   wallet.py71593%37, 129, 155–157
src/algokit/core/tasks/mint
   mint.py74988%123–133
   models.py921782%50, 52, 57, 71–74, 81–90
TOTAL494577284% 

Tests Skipped Failures Errors Time
501 0 💤 0 ❌ 0 🔥 38.407s ⏱️

Please sign in to comment.