diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 602b7093..43391b3f 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -1,6 +1,9 @@ -name: Pull Request validation +name: Codebase validation -on: [pull_request] +on: + pull_request: + schedule: + - cron: "0 8 * * 1" # Each monday 8 AM UTC concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ec4e026e..3fadb576 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: ruff name: ruff description: "Run 'ruff' for extremely fast Python linting" - entry: poetry run ruff + entry: poetry run ruff check language: system "types": [python] args: [--fix, --no-cache] diff --git a/docs/cli/index.md b/docs/cli/index.md index 624ce7e0..0f912df0 100644 --- a/docs/cli/index.md +++ b/docs/cli/index.md @@ -24,48 +24,53 @@ - [Options](#options-3) - [--shell ](#--shell--1) - [config](#config) - - [version-prompt](#version-prompt) + - [container-engine](#container-engine) + - [Options](#options-4) + - [-f, --force](#-f---force) - [Arguments](#arguments-2) + - [ENGINE](#engine) + - [version-prompt](#version-prompt) + - [Arguments](#arguments-3) - [ENABLE](#enable) - [dispenser](#dispenser) - [fund](#fund) - - [Options](#options-4) + - [Options](#options-5) - [-r, --receiver ](#-r---receiver-) - [-a, --amount ](#-a---amount-) - [--whole-units](#--whole-units) - [limit](#limit) - - [Options](#options-5) + - [Options](#options-6) - [--whole-units](#--whole-units-1) - [login](#login) - - [Options](#options-6) + - [Options](#options-7) - [--ci](#--ci) - [-o, --output ](#-o---output-) - [-f, --file ](#-f---file-) - [logout](#logout) - [refund](#refund) - - [Options](#options-7) + - [Options](#options-8) - [-t, --txID ](#-t---txid-) - [doctor](#doctor) - - [Options](#options-8) + - [Options](#options-9) - [-c, --copy-to-clipboard](#-c---copy-to-clipboard) - [explore](#explore) - - [Arguments](#arguments-3) + - [Arguments](#arguments-4) - [NETWORK](#network) - [generate](#generate) - [client](#client) - - [Options](#options-9) + - [Options](#options-10) - [-o, --output ](#-o---output--1) - [-l, --language ](#-l---language-) - [-v, --version ](#-v---version--1) - - [Arguments](#arguments-4) + - [Arguments](#arguments-5) - [APP_SPEC_PATH_OR_DIR](#app_spec_path_or_dir) - [goal](#goal) - - [Options](#options-10) + - [Options](#options-11) - [--console](#--console) - - [Arguments](#arguments-5) + - [Arguments](#arguments-6) - [GOAL_ARGS](#goal_args) - [init](#init) - - [Options](#options-11) + - [Options](#options-12) - [-n, --name ](#-n---name-) - [-t, --template ](#-t---template-) - [--template-url ](#--template-url-) @@ -78,67 +83,82 @@ - [--workspace, --no-workspace](#--workspace---no-workspace) - [-a, --answer ](#-a---answer--) - [localnet](#localnet) + - [codespace](#codespace) + - [Options](#options-13) + - [-m, --machine ](#-m---machine-) + - [-a, --algod-port ](#-a---algod-port-) + - [-i, --indexer-port ](#-i---indexer-port-) + - [-k, --kmd-port ](#-k---kmd-port-) + - [-n, --codespace-name ](#-n---codespace-name-) + - [-r, --repo-url ](#-r---repo-url-) + - [-t, --timeout ](#-t---timeout-) + - [-f, --force](#-f---force-1) + - [config](#config-1) + - [Options](#options-14) + - [-f, --force](#-f---force-2) + - [Arguments](#arguments-7) + - [ENGINE](#engine-1) - [console](#console) - [explore](#explore-1) - [logs](#logs) - - [Options](#options-12) + - [Options](#options-15) - [--follow, -f](#--follow--f) - [--tail ](#--tail-) - [reset](#reset) - - [Options](#options-13) + - [Options](#options-16) - [--update, --no-update](#--update---no-update) - [start](#start) - - [Options](#options-14) + - [Options](#options-17) - [-n, --name ](#-n---name--1) - [status](#status) - [stop](#stop) - [project](#project) - [bootstrap](#bootstrap) - - [Options](#options-15) + - [Options](#options-18) - [--force](#--force) - - [Options](#options-16) + - [Options](#options-19) - [--interactive, --non-interactive, --ci](#--interactive---non-interactive---ci) - [-p, --project-name ](#-p---project-name-) - [-t, --type ](#-t---type-) - - [Options](#options-17) + - [Options](#options-20) - [--interactive, --non-interactive, --ci](#--interactive---non-interactive---ci-1) - [deploy](#deploy) - - [Options](#options-18) + - [Options](#options-21) - [-C, --command ](#-c---command-) - [--interactive, --non-interactive, --ci](#--interactive---non-interactive---ci-2) - [-P, --path ](#-p---path-) - [--deployer ](#--deployer-) - [--dispenser ](#--dispenser-) - [-p, --project-name ](#-p---project-name--1) - - [Arguments](#arguments-6) + - [Arguments](#arguments-8) - [ENVIRONMENT_NAME](#environment_name) - [link](#link) - - [Options](#options-19) + - [Options](#options-22) - [-p, --project-name ](#-p---project-name--2) - [-l, --language ](#-l---language--1) - [-a, --all](#-a---all) - [-f, --fail-fast](#-f---fail-fast) - [-v, --version ](#-v---version--2) - [list](#list) - - [Arguments](#arguments-7) + - [Arguments](#arguments-9) - [WORKSPACE_PATH](#workspace_path) - [run](#run) - [task](#task) - [analyze](#analyze) - - [Options](#options-20) + - [Options](#options-23) - [-r, --recursive](#-r---recursive) - [--force](#--force-1) - [--diff](#--diff) - [-o, --output ](#-o---output--2) - [-e, --exclude ](#-e---exclude-) - - [Arguments](#arguments-8) + - [Arguments](#arguments-10) - [INPUT_PATHS](#input_paths) - [ipfs](#ipfs) - - [Options](#options-21) + - [Options](#options-24) - [-f, --file ](#-f---file--1) - [-n, --name ](#-n---name--2) - [mint](#mint) - - [Options](#options-22) + - [Options](#options-25) - [--creator ](#--creator-) - [-n, --name ](#-n---name--3) - [-u, --unit ](#-u---unit-) @@ -150,37 +170,37 @@ - [--nft, --ft](#--nft---ft) - [-n, --network ](#-n---network-) - [nfd-lookup](#nfd-lookup) - - [Options](#options-23) + - [Options](#options-26) - [-o, --output ](#-o---output--3) - - [Arguments](#arguments-9) + - [Arguments](#arguments-11) - [VALUE](#value) - [opt-in](#opt-in) - - [Options](#options-24) + - [Options](#options-27) - [-a, --account ](#-a---account-) - [-n, --network ](#-n---network--1) - - [Arguments](#arguments-10) + - [Arguments](#arguments-12) - [ASSET_IDS](#asset_ids) - [opt-out](#opt-out) - - [Options](#options-25) + - [Options](#options-28) - [-a, --account ](#-a---account--1) - [--all](#--all) - [-n, --network ](#-n---network--2) - - [Arguments](#arguments-11) + - [Arguments](#arguments-13) - [ASSET_IDS](#asset_ids-1) - [send](#send) - - [Options](#options-26) + - [Options](#options-29) - [-f, --file ](#-f---file--2) - [-t, --transaction ](#-t---transaction-) - [-n, --network ](#-n---network--3) - [sign](#sign) - - [Options](#options-27) + - [Options](#options-30) - [-a, --account ](#-a---account--2) - [-f, --file ](#-f---file--3) - [-t, --transaction ](#-t---transaction--1) - [-o, --output ](#-o---output--4) - [--force](#--force-2) - [transfer](#transfer) - - [Options](#options-28) + - [Options](#options-31) - [-s, --sender ](#-s---sender-) - [-r, --receiver ](#-r---receiver--1) - [--asset, --id ](#--asset---id-) @@ -188,29 +208,29 @@ - [--whole-units](#--whole-units-2) - [-n, --network ](#-n---network--4) - [vanity-address](#vanity-address) - - [Options](#options-29) + - [Options](#options-32) - [-m, --match ](#-m---match-) - [-o, --output ](#-o---output--5) - [-a, --alias ](#-a---alias-) - [--file-path ](#--file-path-) - - [-f, --force](#-f---force) - - [Arguments](#arguments-12) + - [-f, --force](#-f---force-3) + - [Arguments](#arguments-14) - [KEYWORD](#keyword) - [wallet](#wallet) - - [Options](#options-30) + - [Options](#options-33) - [-a, --address ](#-a---address-) - [-m, --mnemonic](#-m---mnemonic) - - [-f, --force](#-f---force-1) - - [Arguments](#arguments-13) + - [-f, --force](#-f---force-4) + - [Arguments](#arguments-15) - [ALIAS_NAME](#alias_name) - - [Arguments](#arguments-14) + - [Arguments](#arguments-16) - [ALIAS](#alias) - - [Options](#options-31) - - [-f, --force](#-f---force-2) - - [Arguments](#arguments-15) + - [Options](#options-34) + - [-f, --force](#-f---force-5) + - [Arguments](#arguments-17) - [ALIAS](#alias-1) - - [Options](#options-32) - - [-f, --force](#-f---force-3) + - [Options](#options-35) + - [-f, --force](#-f---force-6) # algokit @@ -342,6 +362,26 @@ Configure settings used by AlgoKit algokit config [OPTIONS] COMMAND [ARGS]... ``` +### container-engine + +Set the default container engine for use by AlgoKit CLI to run LocalNet images. + +```shell +algokit config container-engine [OPTIONS] [[docker|podman]] +``` + +### Options + + +### -f, --force +Skip confirmation prompts. Defaults to 'yes' to all prompts. + +### Arguments + + +### ENGINE +Optional argument + ### version-prompt Controls whether AlgoKit checks and prompts for new versions. @@ -636,6 +676,74 @@ Manage the AlgoKit LocalNet. algokit localnet [OPTIONS] COMMAND [ARGS]... ``` +### codespace + +Manage the AlgoKit LocalNet in GitHub Codespaces. + +```shell +algokit localnet codespace [OPTIONS] +``` + +### Options + + +### -m, --machine +The GitHub Codespace machine type to use. Defaults to base tier. + + +* **Options** + + basicLinux32gb | standardLinux32gb | premiumLinux | largePremiumLinux + + + +### -a, --algod-port +The port for the Algorand daemon. Defaults to 4001. + + +### -i, --indexer-port +The port for the Algorand indexer. Defaults to 8980. + + +### -k, --kmd-port +The port for the Algorand kmd. Defaults to 4002. + + +### -n, --codespace-name +The name of the codespace. Defaults to 'algokit-localnet_timestamp'. + + +### -r, --repo-url +The URL of the repository. Defaults to algokit base template repo. + + +### -t, --timeout +Default max runtime timeout in minutes. Upon hitting the timeout a codespace will be shutdown to prevent accidental spending over GitHub Codespaces quota. Defaults to 4 hours. + + +### -f, --force +Force delete previously used codespaces with {CODESPACE_NAME_PREFIX}\* name prefix and skip prompts. Defaults to explicitly prompting for confirmation. + +### config + +Set the default container engine for use by AlgoKit CLI to run LocalNet images. + +```shell +algokit localnet config [OPTIONS] [[docker|podman]] +``` + +### Options + + +### -f, --force +Skip confirmation prompts. Defaults to 'yes' to all prompts. + +### Arguments + + +### ENGINE +Optional argument + ### console Run the Algorand goal CLI against the AlgoKit LocalNet via a Bash console so you can execute multiple goal commands and/or interact with a filesystem. diff --git a/docs/features/localnet.md b/docs/features/localnet.md index 236eb3fa..7c90f9f0 100644 --- a/docs/features/localnet.md +++ b/docs/features/localnet.md @@ -6,9 +6,11 @@ AlgoKit LocalNet uses Docker images that are optimised for a great dev experienc The philosophy we take with AlgoKit LocalNet is that you should treat it as an ephemeral network. This means assume it could be reset at any time - don't store data on there that you can't recover / recreate. We have optimised the AlgoKit LocalNet experience to minimise situations where the network will get reset to improve the experience, but it can and will still happen in a number of situations. +> For details on executing `algokit localnet` without `docker` or `podman` refer to the [codespaces](#codespaces) section. + ## Prerequisites -AlgoKit LocalNet relies on Docker and Docker Compose being present and running on your system. +AlgoKit LocalNet relies on Docker and Docker Compose being present and running on your system. Alternatively, you can use Podman as a replacement for Docker see [Podman support](#podman-support). You can install Docker by following the [official installation instructions](https://docs.docker.com/get-docker/). Most of the time this will also install Docker Compose, but if not you can [follow the instructions](https://docs.docker.com/compose/install/) for that too. @@ -16,6 +18,10 @@ If you are on Windows then you will need WSL 2 installed first, for which you ca Alternatively, the Windows 10/11 Pro+ supported [Hyper-V backend](https://docs.docker.com/desktop/install/windows-install/) for Docker can be used instead of the WSL 2 backend. +### Podman support + +If you prefer to use [Podman](https://podman.io/) as your container engine, make sure to install and configure Podman first. Then you can set the default container engine that AlgoKit will use, by running: `algokit config container-engine podman`. See [Container-based LocalNet](#container-based-localnet) for more details. + ## Known issues The AlgoKit LocalNet is built with 30,000 participation keys generated and after 30,000 rounds is reached it will no longer be able to add rounds. At this point you can simply reset the LocalNet to continue development. Participation keys are slow to generate hence why they are pre-generated to improve experience. @@ -24,7 +30,17 @@ The AlgoKit LocalNet is built with 30,000 participation keys generated and after We rely on the official Algorand docker images for Indexer, Conduit and Algod, which means that AlgoKit LocalNet is supported on Windows, Linux and Mac on Intel and AMD chipsets (including Apple Silicon). -## Functionality +## Container-based LocalNet + +AlgoKit cli supports both [Docker](https://www.docker.com/) and [Podman](https://podman.io/) as container engines. While `docker` is used by default, executing the below: + +``` +algokit config container-engine +# or +algokit config container-engine podman|docker +``` + +Will set the default container engine to use when executing `localnet` related commands via `subprocess`. ### Creating / Starting the LocalNet @@ -120,3 +136,27 @@ AlgoKit Utils provides methods to help you do this: - Python - [`ensure_funded`](https://algorandfoundation.github.io/algokit-utils-py/html/apidocs/algokit_utils/algokit_utils.html#algokit_utils.ensure_funded) and [`get_dispenser_account`](https://algorandfoundation.github.io/algokit-utils-py/html/apidocs/algokit_utils/algokit_utils.html#algokit_utils.get_dispenser_account) For more details about the `AlgoKit localnet` command, please refer to the [AlgoKit CLI reference documentation](../cli/index.md#localnet). + +## GitHub Codespaces-based LocalNet + +The AlgoKit LocalNet feature also supports running the LocalNet in a GitHub Codespace with port forwarding by utilizing the [GitHub CLI](https://github.com/cli/gh). This allows you to run the LocalNet without the need to use Docker. This is especially useful for scenarios where certain hardware or software limitations may prevent you from being able to run Docker. + +To run the LocalNet in a GitHub Codespace, you can use the `algokit localnet codespace` command. +By default without `--force` flag it will prompt you to delete stale codespaces created earlier (if any). Upon termination it will also prompt to delete the codespace that was used prior to termination. + +Running an interactive session ensures that you have control over the lifecycle of your Codespace, preventing unnecessary usage and potential costs. GitHub Codespaces offers a free tier with certain limits, which you can review in the [GitHub Codespaces documentation](https://docs.github.com/en/codespaces/overview#pricing). + +### Options + +- `-m`, `--machine`: Specifies the GitHub Codespace machine type to use. Defaults to `basicLinux32gb`. Available options are `basicLinux32gb`, `standardLinux32gb`, `premiumLinux`, and `largePremiumLinux`. Refer to [GitHub Codespaces documentation](https://docs.github.com/en/codespaces/overview/machine-types) for more details. +- `-a`, `--algod-port`: Sets the port for the Algorand daemon. Defaults to `4001`. +- `-i`, `--indexer-port`: Sets the port for the Algorand indexer. Defaults to `8980`. +- `-k`, `--kmd-port`: Sets the port for the Algorand kmd. Defaults to `4002`. +- `-n`, `--codespace-name`: Specifies the name of the codespace. Defaults to a random name with a timestamp. +- `-t`, `--timeout`: Max duration for running the port forwarding process. Defaults to 1 hour. This timeout ensures the codespace **will automatically shut down** after the specified duration to prevent accidental overspending of free quota on GitHub Codespaces. [More details](https://docs.github.com/en/codespaces/setting-your-user-preferences/setting-your-timeout-period-for-github-codespaces). +- `-r`, `--repo-url`: The URL of the repository to use. Defaults to the AlgoKit base template repository (`algorandfoundation/algokit-base-template`). The reason why algokit-base-template is used by default is due to [.devcontainer.json](https://github.com/algorandfoundation/algokit-base-template/blob/main/template_content/.devcontainer.json) which defines the scripts that take care of setting up AlgoKit CLI during container start. You can use any custom repo as a base, however it's important to ensure the reference [.devcontainer.json](https://github.com/algorandfoundation/algokit-base-template/blob/main/template_content/.devcontainer.json) file exists in your repository **otherwise there will be no ports to forward from the codespace**. +- `--force`, `-f`: Force deletes stale codespaces and skips confirmation prompts. Defaults to explicitly prompting for confirmation. + +For more details about managing LocalNet in GitHub Codespaces, please refer to the [AlgoKit CLI reference documentation](../cli/index.md#codespace). + +> Tip: By specifying alternative port values it is possible to have several LocalNet instances running where one is using default ports via `algokit localnet start` with Docker | Podman and the other relies on port forwarding via `algokit localnet codespace`. diff --git a/docs/tutorials/intro.md b/docs/tutorials/intro.md index 9c7960ec..0139fbe8 100644 --- a/docs/tutorials/intro.md +++ b/docs/tutorials/intro.md @@ -21,7 +21,7 @@ Before proceeding, ensure you have the following components installed: - [Python 3.10](https://www.python.org/downloads/) or higher - [pipx](https://pypa.github.io/pipx/#on-linux-install-via-pip-requires-pip-190-or-later) - [git](https://github.com/git-guides/install-git#install-git) -- [Docker](https://docs.docker.com/desktop/install/mac-install/) +- [Docker](https://docs.docker.com/desktop/install/mac-install/) (or [Podman](https://podman.io/getting-started/installation/), see [details](../features/localnet.md#podman-support)) - [VSCode](https://code.visualstudio.com/download) ## Install AlgoKit 🛠 diff --git a/pyproject.toml b/pyproject.toml index 78ea27fd..47ab5841 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -147,7 +147,7 @@ lint.dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" # Assume Python 3.10. target-version = "py310" -[tool.ruff.per-file-ignores] +[tool.ruff.lint.per-file-ignores] "tests/**/test_*.py" = ["PLR0913"] # too many args [tool.ruff.lint.flake8-annotations] diff --git a/src/algokit/cli/__init__.py b/src/algokit/cli/__init__.py index 18d59b2d..558fafdb 100644 --- a/src/algokit/cli/__init__.py +++ b/src/algokit/cli/__init__.py @@ -15,8 +15,8 @@ from algokit.cli.project.deploy import deploy_command from algokit.cli.task import task_group from algokit.core.conf import PACKAGE_NAME +from algokit.core.config_commands.version_prompt import do_version_prompt, skip_version_check_option from algokit.core.log_handlers import color_option, verbose_option -from algokit.core.version_prompt import do_version_prompt, skip_version_check_option HIDDEN_COMMANDS: dict[str, click.Command] = {"deploy": deploy_command, "bootstrap": bootstrap_group} diff --git a/src/algokit/cli/codespace.py b/src/algokit/cli/codespace.py new file mode 100644 index 00000000..76e5b7ba --- /dev/null +++ b/src/algokit/cli/codespace.py @@ -0,0 +1,159 @@ +import logging +import subprocess +from time import time +from typing import Any + +import click + +from algokit.core import questionary_extensions +from algokit.core.codespace import ( + CODESPACE_FORWARD_TIMEOUT_MAX, + CODESPACE_FORWARD_TIMEOUT_MIN, + CODESPACE_NAME_PREFIX, + authenticate_with_github, + create_codespace, + delete_codespace, + delete_codespaces_with_prefix, + ensure_github_cli_installed, + forward_ports_for_codespace, + is_codespace_ready, + list_github_codespaces, +) + +logger = logging.getLogger(__name__) + + +def _validate_run_timeout(_ctx: click.Context, _param: click.Parameter, value: int) -> int: + if value < CODESPACE_FORWARD_TIMEOUT_MIN or value > CODESPACE_FORWARD_TIMEOUT_MAX: + raise click.BadParameter( + f"Timeout must be between {CODESPACE_FORWARD_TIMEOUT_MIN} and {CODESPACE_FORWARD_TIMEOUT_MAX} minutes." + ) + return value + + +@click.command("codespace") +@click.option( + "-m", + "--machine", + type=click.Choice( + ["basicLinux32gb", "standardLinux32gb", "premiumLinux", "largePremiumLinux"], case_sensitive=True + ), + default="basicLinux32gb", + required=False, + help="The GitHub Codespace machine type to use. Defaults to base tier.", +) +@click.option( + "-a", "--algod-port", default=4001, required=False, help="The port for the Algorand daemon. Defaults to 4001." +) +@click.option( + "-i", "--indexer-port", default=8980, required=False, help="The port for the Algorand indexer. Defaults to 8980." +) +@click.option("-k", "--kmd-port", default=4002, required=False, help="The port for the Algorand kmd. Defaults to 4002.") +@click.option( + "-n", + "--codespace-name", + default="", + required=False, + help=f"The name of the codespace. Defaults to '{CODESPACE_NAME_PREFIX}_timestamp'.", +) +@click.option( + "-r", + "--repo-url", + required=False, + default="algorandfoundation/algokit-base-template", + help="The URL of the repository. Defaults to algokit base template repo.", +) +@click.option( + "-t", + "--timeout", + "timeout_minutes", + default=240, + required=False, + callback=_validate_run_timeout, + help="Default max runtime timeout in minutes. Upon hitting the timeout a codespace will be shutdown to " + "prevent accidental spending over GitHub Codespaces quota. Defaults to 4 hours.", +) +@click.option( + "--force", + "-f", + is_flag=True, + required=False, + default=False, + type=click.BOOL, + help=( + "Force delete previously used codespaces with `{CODESPACE_NAME_PREFIX}*` name prefix and skip prompts. " + "Defaults to explicitly prompting for confirmation." + ), +) +def codespace_command( # noqa: PLR0913 + *, + machine: str, + algod_port: int, + indexer_port: int, + kmd_port: int, + codespace_name: str, + repo_url: str, + timeout_minutes: int, + force: bool, +) -> None: + """Manage the AlgoKit LocalNet in GitHub Codespaces.""" + ensure_github_cli_installed() + + if not authenticate_with_github(): + return + + codespaces = list_github_codespaces() + + # Delete existing codespaces with the default name + if codespaces and ( + force + or questionary_extensions.prompt_confirm( + f"Delete previously used codespaces with `{CODESPACE_NAME_PREFIX}*` name prefix?", default=True + ) + ): + delete_codespaces_with_prefix(codespaces, CODESPACE_NAME_PREFIX) + + # Create a new codespace + codespace_name = codespace_name or f"{CODESPACE_NAME_PREFIX}_{int(time())}" + # Add a 5 minute timeout buffer, so the codespace doesn't terminate before the port forwarding + codespace_timeout = ( + (timeout_minutes + 5) + if (timeout_minutes + 5) < CODESPACE_FORWARD_TIMEOUT_MAX + else CODESPACE_FORWARD_TIMEOUT_MAX + ) + create_codespace( + repo_url, + codespace_name, + machine, + codespace_timeout, + ) + + codespace_data: dict[str, Any] | None = None + + try: + logger.info(f"Waiting for codespace {codespace_name} to be ready...") + codespace_data = is_codespace_ready(codespace_name) + if not codespace_data: + raise RuntimeError("Error creating codespace. Please check your internet connection and try again.") + + logger.info(f"Codespace {codespace_name} is now ready.") + logger.warning( + "Keep the terminal open during the LocalNet session. " + "Terminating the session will delete the codespace instance." + ) + + forward_ports_for_codespace( + codespace_data["name"], algod_port, kmd_port, indexer_port, timeout=timeout_minutes * 60 + ) + logger.info("LocalNet started in GitHub Codespace") + + except subprocess.TimeoutExpired: + logger.warning("Timeout reached. Shutting down the codespace...") + except KeyboardInterrupt: + logger.warning("Keyboard interrupt received. Shutting down the codespace...") + except Exception as e: + logger.error(e) + finally: + logger.info("Exiting...") + if codespace_data: + delete_codespace(codespace_data=codespace_data, force=force) diff --git a/src/algokit/cli/config.py b/src/algokit/cli/config.py index 3034a02a..05c7490c 100644 --- a/src/algokit/cli/config.py +++ b/src/algokit/cli/config.py @@ -1,6 +1,7 @@ import click -from algokit.core.version_prompt import version_prompt_configuration_command +from algokit.core.config_commands.container_engine import container_engine_configuration_command +from algokit.core.config_commands.version_prompt import version_prompt_configuration_command @click.group("config", short_help="Configure AlgoKit settings.") @@ -9,3 +10,4 @@ def config_group() -> None: config_group.add_command(version_prompt_configuration_command) +config_group.add_command(container_engine_configuration_command) diff --git a/src/algokit/cli/doctor.py b/src/algokit/cli/doctor.py index 8671df34..ca77c641 100644 --- a/src/algokit/cli/doctor.py +++ b/src/algokit/cli/doctor.py @@ -7,13 +7,13 @@ import pyclip # type: ignore[import-untyped] from algokit.core.conf import get_current_package_version +from algokit.core.config_commands.version_prompt import get_latest_github_version from algokit.core.doctor import DoctorResult, check_dependency from algokit.core.sandbox import ( - DOCKER_COMPOSE_MINIMUM_VERSION, - DOCKER_COMPOSE_VERSION_COMMAND, + COMPOSE_VERSION_COMMAND, + get_min_compose_version, ) from algokit.core.utils import is_windows as get_is_windows -from algokit.core.version_prompt import get_latest_github_version logger = logging.getLogger(__name__) @@ -40,25 +40,28 @@ def doctor_command(*, copy_to_clipboard: bool) -> None: Will search the system for AlgoKit dependencies and show their versions, as well as identifying any potential issues.""" + from algokit.core.config_commands.container_engine import get_container_engine + os_type = platform.system() is_windows = get_is_windows() + container_engine = get_container_engine() + docs_url = f"https://{container_engine}.io" + compose_minimum_version = get_min_compose_version() service_outputs = { "timestamp": DoctorResult(ok=True, output=dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat()), "AlgoKit": _get_algokit_version_output(), "AlgoKit Python": DoctorResult(ok=True, output=f"{sys.version} (location: {sys.prefix})"), "OS": DoctorResult(ok=True, output=platform.platform()), - "docker": check_dependency( - ["docker", "--version"], - missing_help=[ - "Docker required to run `algokit localnet` command; install via https://docs.docker.com/get-docker/" - ], + container_engine: check_dependency( + [container_engine, "--version"], + missing_help=[f"`{container_engine}` required to run `algokit localnet` command; install via {docs_url}"], ), - "docker compose": check_dependency( - DOCKER_COMPOSE_VERSION_COMMAND, - minimum_version=DOCKER_COMPOSE_MINIMUM_VERSION, + f"{container_engine} compose": check_dependency( + COMPOSE_VERSION_COMMAND, + minimum_version=compose_minimum_version, minimum_version_help=[ - f"Docker Compose {DOCKER_COMPOSE_MINIMUM_VERSION} required to run `algokit localnet` command;", - "install via https://docs.docker.com/compose/install/", + f"{container_engine.capitalize()} Compose {compose_minimum_version} required to run `algokit localnet` command;", # noqa: E501 + f"install via {docs_url}", ], ), "git": check_dependency( @@ -104,7 +107,7 @@ def doctor_command(*, copy_to_clipboard: bool) -> None: elif os_type == "Darwin": service_outputs["brew"] = check_dependency(["brew", "--version"]) - critical_services = ["docker", "docker compose", "git"] + critical_services = [container_engine, f"{container_engine} compose", "git"] # Print the status details for key, value in service_outputs.items(): if value.ok: diff --git a/src/algokit/cli/goal.py b/src/algokit/cli/goal.py index b0d5ae9c..7eec1a68 100644 --- a/src/algokit/cli/goal.py +++ b/src/algokit/cli/goal.py @@ -3,13 +3,14 @@ import click from algokit.core import proc +from algokit.core.config_commands.container_engine import get_container_engine from algokit.core.goal import ( get_volume_mount_path_docker, get_volume_mount_path_local, post_process, preprocess_command_args, ) -from algokit.core.sandbox import DEFAULT_NAME, ComposeFileStatus, ComposeSandbox +from algokit.core.sandbox import SANDBOX_BASE_NAME, ComposeFileStatus, ComposeSandbox logger = logging.getLogger(__name__) @@ -35,28 +36,35 @@ def goal_command(*, console: bool, goal_args: list[str]) -> None: Look at https://developer.algorand.org/docs/clis/goal/goal/ for more information. """ goal_args = list(goal_args) + container_engine = get_container_engine() try: - proc.run(["docker", "version"], bad_return_code_error_message="Docker engine isn't running; please start it.") + proc.run( + [container_engine, "version"], + bad_return_code_error_message=f"{container_engine} engine isn't running; please start it.", + ) except OSError as ex: # an IOError (such as PermissionError or FileNotFoundError) will only occur if "docker" # isn't an executable in the user's path, which means docker isn't installed + docs_url = ( + "https://www.docker.com/get-started/" if container_engine == "docker" else "https://podman.io/get-started" + ) raise click.ClickException( - "Docker not found; please install Docker and add to path.\n" - "See https://docs.docker.com/get-docker/ for more information." + f"{container_engine} not found; please install {container_engine} and add to path.\n" + f"See {docs_url} for more information." ) from ex sandbox = ComposeSandbox.from_environment() if sandbox is None: sandbox = ComposeSandbox() - if sandbox.name != DEFAULT_NAME: + if sandbox.name != SANDBOX_BASE_NAME: logger.info("A named LocalNet is running, goal command will be executed against the named LocalNet") volume_mount_path_local = get_volume_mount_path_local(directory_name=sandbox.name) volume_mount_path_docker = get_volume_mount_path_docker() compose_file_status = sandbox.compose_file_status() - if compose_file_status is not ComposeFileStatus.UP_TO_DATE and sandbox.name == DEFAULT_NAME: + if compose_file_status is not ComposeFileStatus.UP_TO_DATE and sandbox.name == SANDBOX_BASE_NAME: raise click.ClickException("LocalNet definition is out of date; please run `algokit localnet reset` first!") ps_result = sandbox.ps("algod") match ps_result: @@ -70,9 +78,9 @@ def goal_command(*, console: bool, goal_args: list[str]) -> None: if goal_args: logger.warning("--console opens an interactive shell, remaining arguments are being ignored") logger.info("Opening Bash console on the algod node; execute `exit` to return to original console") - result = proc.run_interactive(f"docker exec -it -w /root algokit_{sandbox.name}_algod bash".split()) + result = proc.run_interactive(f"{container_engine} exec -it -w /root algokit_{sandbox.name}_algod bash".split()) else: - cmd = f"docker exec --interactive --workdir /root algokit_{sandbox.name}_algod goal".split() + cmd = f"{container_engine} exec --interactive --workdir /root algokit_{sandbox.name}_algod goal".split() input_files, output_files, goal_args = preprocess_command_args( goal_args, volume_mount_path_local, volume_mount_path_docker ) diff --git a/src/algokit/cli/localnet.py b/src/algokit/cli/localnet.py index 92d49aa2..be6c1418 100644 --- a/src/algokit/cli/localnet.py +++ b/src/algokit/cli/localnet.py @@ -1,18 +1,22 @@ import logging import click +import questionary +from algokit.cli.codespace import codespace_command from algokit.cli.explore import explore_command from algokit.cli.goal import goal_command from algokit.core import proc +from algokit.core.config_commands.container_engine import get_container_engine, save_container_engine from algokit.core.sandbox import ( - DEFAULT_NAME, - DOCKER_COMPOSE_MINIMUM_VERSION, - DOCKER_COMPOSE_VERSION_COMMAND, + COMPOSE_VERSION_COMMAND, + SANDBOX_BASE_NAME, ComposeFileStatus, ComposeSandbox, + ContainerEngine, fetch_algod_status_data, fetch_indexer_status_data, + get_min_compose_version, ) from algokit.core.utils import extract_version_triple, is_minimum_version @@ -20,41 +24,96 @@ @click.group("localnet", short_help="Manage the AlgoKit LocalNet.") -def localnet_group() -> None: +@click.pass_context +def localnet_group(ctx: click.Context) -> None: + if ctx.invoked_subcommand and "codespace" in ctx.invoked_subcommand or not ctx.invoked_subcommand: + return + try: - compose_version_result = proc.run(DOCKER_COMPOSE_VERSION_COMMAND) + compose_version_result = proc.run(COMPOSE_VERSION_COMMAND) except OSError as ex: # an IOError (such as PermissionError or FileNotFoundError) will only occur if "docker" # isn't an executable in the user's path, which means docker isn't installed raise click.ClickException( - "Docker not found; please install Docker and add to path.\n" - "See https://docs.docker.com/get-docker/ for more information." + "Container engine not found; please install Docker or Podman and add to path." ) from ex if compose_version_result.exit_code != 0: raise click.ClickException( - "Docker Compose not found; please install Docker Compose and add to path.\n" - "See https://docs.docker.com/compose/install/ for more information." + "Container engine compose not found; please install Docker Compose or Podman Compose and add to path." ) + compose_minimum_version = get_min_compose_version() try: compose_version_str = extract_version_triple(compose_version_result.output) - compose_version_ok = is_minimum_version(compose_version_str, DOCKER_COMPOSE_MINIMUM_VERSION) + compose_version_ok = is_minimum_version(compose_version_str, compose_minimum_version) except Exception: logger.warning( - "Unable to extract docker compose version from output: \n" + "Unable to extract compose version from output: \n" + compose_version_result.output - + f"\nPlease ensure a minimum of compose v{DOCKER_COMPOSE_MINIMUM_VERSION} is used", + + f"\nPlease ensure a minimum of compose v{compose_minimum_version} is used", exc_info=True, ) else: if not compose_version_ok: raise click.ClickException( - f"Minimum docker compose version supported: v{DOCKER_COMPOSE_MINIMUM_VERSION}, " + f"Minimum compose version supported: v{compose_minimum_version}, " f"installed = v{compose_version_str}\n" - "Please update your Docker install" + "Please update your compose install" ) - proc.run(["docker", "version"], bad_return_code_error_message="Docker engine isn't running; please start it.") + if ctx.invoked_subcommand and ctx.invoked_subcommand == "config": + return + + proc.run( + [get_container_engine(), "version"], + bad_return_code_error_message="Container engine isn't running; please start it.", + ) + + +@localnet_group.command("config", short_help="Configure the container engine for AlgoKit LocalNet.") +@click.argument("engine", required=False, type=click.Choice(["docker", "podman"])) +@click.option( + "--force", + "-f", + is_flag=True, + required=False, + default=False, + type=click.BOOL, + help=("Skip confirmation prompts. " "Defaults to 'yes' to all prompts."), +) +def config_command(*, engine: str | None, force: bool) -> None: + """Set the default container engine for use by AlgoKit CLI to run LocalNet images.""" + if engine is None: + current_engine = get_container_engine() + choices = [ + f"Docker {'(Active)' if current_engine == ContainerEngine.DOCKER else ''}".strip(), + f"Podman {'(Active)' if current_engine == ContainerEngine.PODMAN else ''}".strip(), + ] + engine = questionary.select("Which container engine do you prefer?", choices=choices).ask() + if engine is None: + raise click.ClickException("No valid container engine selected. Aborting...") + engine = engine.split()[0].lower() + + sandbox = ComposeSandbox.from_environment() + has_active_instance = sandbox is not None and ( + force + or click.confirm( + f"Detected active localnet instance, would you like to restart it with '{engine}'?", + default=True, + ) + ) + if sandbox and has_active_instance: + sandbox.down() + save_container_engine(engine) + sandbox.write_compose_file() + sandbox.up() + else: + save_container_engine(engine) + + logger.info(f"Container engine set to `{engine}`") + + +localnet_group.add_command(config_command) @localnet_group.command("start", short_help="Start the AlgoKit LocalNet.") @@ -69,7 +128,7 @@ def localnet_group() -> None: ) def start_localnet(name: str | None) -> None: sandbox = ComposeSandbox.from_environment() - full_name = f"{DEFAULT_NAME}_{name}" if name is not None else DEFAULT_NAME + full_name = f"{SANDBOX_BASE_NAME}_{name}" if name is not None else SANDBOX_BASE_NAME if sandbox is not None and full_name != sandbox.name: logger.debug("LocalNet is already running.") if click.confirm("This will stop any running AlgoKit LocalNet instance. Are you sure?", default=True): @@ -125,7 +184,7 @@ def reset_localnet(*, update: bool) -> None: if compose_file_status is ComposeFileStatus.MISSING: logger.debug("Existing LocalNet not found; creating from scratch...") sandbox.write_compose_file() - elif sandbox.name == DEFAULT_NAME: + elif sandbox.name == SANDBOX_BASE_NAME: sandbox.down() if compose_file_status is not ComposeFileStatus.UP_TO_DATE: logger.info("LocalNet definition is out of date; updating it to latest") @@ -159,6 +218,12 @@ def localnet_status() -> None: sandbox = ComposeSandbox.from_environment() if sandbox is None: sandbox = ComposeSandbox() + + logger.info("# container engine") + logger.info( + "Name: " + click.style(get_container_engine(), bold=True) + " (change with `algokit config container-engine`)" + ) + ps = sandbox.ps() ps_by_name = {stats["Service"]: stats for stats in ps} # if any of the required containers does not exist (ie it's not just stopped but hasn't even been created), @@ -226,3 +291,6 @@ def localnet_explore(context: click.Context) -> None: def localnet_logs(ctx: click.Context, *, follow: bool, tail: str) -> None: sandbox = ComposeSandbox() sandbox.logs(follow=follow, no_color=ctx.color is False, tail=tail) + + +localnet_group.add_command(codespace_command) diff --git a/src/algokit/cli/tasks/analyze.py b/src/algokit/cli/tasks/analyze.py index 9412dbce..18c7a480 100644 --- a/src/algokit/cli/tasks/analyze.py +++ b/src/algokit/cli/tasks/analyze.py @@ -7,11 +7,11 @@ from algokit.core.tasks.analyze import ( TEALER_SNAPSHOTS_ROOT, + ensure_tealer_installed, generate_report_filename, generate_summaries, generate_tealer_command, has_baseline_diff, - install_tealer_if_needed, load_tealer_report, prepare_artifacts_folders, run_tealer, @@ -162,7 +162,7 @@ def analyze( # noqa: PLR0913, C901 """ # Install tealer if needed - install_tealer_if_needed() + ensure_tealer_installed() detectors_to_exclude = sorted(set(detectors_to_exclude)) input_files = get_input_files(input_paths=input_paths, recursive=recursive) diff --git a/src/algokit/core/codespace.py b/src/algokit/core/codespace.py new file mode 100644 index 00000000..c4e2892d --- /dev/null +++ b/src/algokit/core/codespace.py @@ -0,0 +1,403 @@ +import json +import logging +import subprocess +import tempfile +import time +from datetime import datetime +from functools import cache +from pathlib import Path +from typing import Any + +import click +import httpx + +from algokit.core import proc, questionary_extensions +from algokit.core.utils import is_windows, run_with_animation + +logger = logging.getLogger(__name__) + +GH_WEBI_INSTALLER_URL = "https://webi.sh/gh" +CODESPACE_PORT_FORWARD_RETRY_SECONDS = 5 +CODESPACE_NAME_PREFIX = "algokit-localnet" +CODESPACE_CREATE_TIMEOUT = 60 +CODESPACE_CREATE_RETRY_TIMEOUT = 10 +CODESPACE_CONTAINER_AVAILABLE = "Available" +CODESPACE_TOO_MANY_ERROR_MSG = "too many codespaces" +CODESPACE_LOADING_MSG = "Provisioning a new codespace instance..." + +# https://docs.github.com/en/codespaces/setting-your-user-preferences/setting-your-timeout-period-for-github-codespaces +CODESPACE_FORWARD_TIMEOUT_MIN = 1 +CODESPACE_FORWARD_TIMEOUT_MAX = 240 + + +def _is_port_in_use(port: int) -> bool: + import socket + + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + return s.connect_ex(("localhost", port)) == 0 + + +def _find_next_available_port(start_port: int, ignore_ports: list[int]) -> int: + port = start_port + while _is_port_in_use(port) or port in ignore_ports: + port += 1 + return port + + +def _try_forward_ports_once(ports: list[tuple[int, int]], codespace_name: str, timeout: int) -> bool: + command = [ + "gh", + "codespace", + "ports", + "forward", + "--codespace", + codespace_name, + *(f"{external_port}:{internal_port}" for internal_port, external_port in ports), + ] + + try: + logger.info( + f"NOTE: This codespace port-forwarding attempt will auto shut down at " + f"{datetime.fromtimestamp(time.time() + timeout).astimezone().strftime('%Y-%m-%d %H:%M:%S %Z')}." + " See https://docs.github.com/en/codespaces/overview#pricing for more details." + ) + response = proc.run_interactive(command, timeout=timeout) + return response.exit_code == 0 + except subprocess.TimeoutExpired as e: + logger.debug(f"Timed out trying to forward ports for codespace {codespace_name} {e}") + raise e + except Exception as e: + logger.error(f"Port forwarding attempt failed with error: {e}") + return False + + +def _write_temp_script(script_content: str, script_extension: str) -> Path: + """ + Writes the script content to a temporary file and returns the file path. + """ + with tempfile.NamedTemporaryFile(delete=False, suffix=f".{script_extension}", mode="w") as tmp_file: + script_path = Path(tmp_file.name) + script_path.write_text(script_content) + script_path.chmod(0o755) + return script_path + + +def _run_powershell_script(script_path: Path) -> None: + """ + Runs the PowerShell script. + """ + _ensure_command_available( + ["powershell", "-command", "(Get-Variable PSVersionTable -ValueOnly).PSVersion"], + "PowerShell is required but not found on this system. Refer to `https://aka.ms/install-powershell` " + "for details.", + ) + proc.run(["powershell", "-File", str(script_path)]) + + +def _run_unix_script(script_path: Path) -> None: + """ + Runs the Unix shell script. + """ + shell = _find_available_shell() + proc.run([shell, str(script_path)]) + + +def _ensure_command_available(command: list[str], error_message: str) -> None: + """ + Ensures that the specified command is available on the system. + """ + try: + proc.run(command) + except Exception as e: + raise RuntimeError(error_message) from e + + +def _find_available_shell() -> str: + """ + Finds an available shell (bash or zsh) on the system. + """ + try: + _ensure_command_available( + ["bash", "--version"], + "Bash is required but not found on this system. Checking whether zsh is available...", + ) + return "bash" + except RuntimeError: + _ensure_command_available( + ["zsh", "--version"], + "Neither Bash nor Zsh is found on this Linux system. " + "Please make sure to install one of them before running " + "`algokit localnet codespace`.", + ) + + return "zsh" + + +def ensure_github_cli_installed() -> None: + """ + Ensures GitHub CLI (`gh`) is installed, installing it if necessary. + """ + try: + proc.run(["gh", "--version"]) + except Exception as err: + logger.info("Installing gh...") + try: + install_github_cli_via_webi() + except Exception as e: + logger.error(f"Failed to automatically install gh cli: {e}") + logger.error( + "Please install `gh cli` manually by following official documentation at https://cli.github.com/" + ) + raise + logger.info("gh installed successfully!") + logger.warning( + "Restart your terminal to activate the `gh` CLI and re-run `algokit localnet codespace` to get started..." + ) + raise click.exceptions.Exit(code=0) from err + + +def install_github_cli_via_webi() -> None: + """ + Installs `gh` using the `webi.sh` script. + """ + response = httpx.get(f'https://webi.{"ms" if is_windows() else "sh"}/gh') + response.raise_for_status() + + script_extension = "ps1" if is_windows() else "sh" + script_path = _write_temp_script(response.text, script_extension) + + if is_windows(): + _run_powershell_script(script_path) + else: + _run_unix_script(script_path) + + +@cache +def is_github_cli_authenticated() -> bool: + """ + Checks if the user is authenticated with GitHub CLI and has the 'codespace' scope. + """ + try: + result = proc.run(["gh", "auth", "status"]) + + # Normalize output for easier parsing + normalized_output = " ".join(result.output.splitlines()).lower() + + # Check for authentication and 'codespace' scope + authenticated = "logged in" in normalized_output + has_codespace_scope = "codespace" in normalized_output + + if not authenticated: + logger.error("GitHub CLI authentication check failed. Please login with `gh auth login -s codespace`.") + if not has_codespace_scope: + logger.error( + "Required 'codespace' scope is missing. " + "Please ensure you have the 'codespace' scope by running " + "`gh auth refresh-token -s codespace`." + ) + + return authenticated and has_codespace_scope + except subprocess.CalledProcessError: + logger.error("GitHub CLI authentication check failed. Please login with `gh auth login -s codespace`.") + return False + + +def authenticate_with_github() -> bool: + """ + Logs the user into GitHub Codespace. + """ + if is_github_cli_authenticated(): + return True + + result = proc.run_interactive( + ["gh", "auth", "login", "-s", "codespace"], + ) + if result.exit_code != 0: + logger.error("Failed to start LocalNet in GitHub Codespace") + return False + logger.info("Logged in to GitHub Codespace") + return True + + +def list_github_codespaces() -> list[str]: + """ + Lists available GitHub Codespaces. + """ + if not is_github_cli_authenticated(): + return [] + + result = proc.run(["gh", "codespace", "list"], pass_stdin=True) + + if result.exit_code != 0: + logger.error("Failed to log in to GitHub Codespaces. Run with -v flag for more details.") + logger.debug(result.output, result.exit_code) + return [] + + return [line.split("\t")[0] for line in result.output.splitlines()] + + +def forward_ports_for_codespace( # noqa: PLR0913 + codespace_name: str, + algod_port: int, + kmd_port: int, + indexer_port: int, + *, + max_retries: int = 3, + timeout: int = CODESPACE_FORWARD_TIMEOUT_MAX * 60, +) -> None: + """ + Forwards specified ports for a GitHub Codespace with retries. + """ + ports = [ + (algod_port, 4001), + (kmd_port, 4002), + (indexer_port, 8980), + ] + + occupied_ports = [port for port in [algod_port, kmd_port, indexer_port] if _is_port_in_use(port)] + + if occupied_ports: + logger.warning(f"Ports {', '.join(map(str, occupied_ports))} are already in use!") + if questionary_extensions.prompt_confirm("Retry on next available ports?", default=True): + logger.warning( + "NOTE: Ensure to update the port numbers in your Algorand related configuration files (if any)." + ) + next_algod_port = _find_next_available_port(algod_port, occupied_ports) + next_kmd_port = _find_next_available_port(kmd_port, [next_algod_port, *occupied_ports]) + next_indexer_port = _find_next_available_port( + indexer_port, [next_algod_port, next_kmd_port, *occupied_ports] + ) + logger.info( + f"Retrying with ports {next_algod_port} (was {algod_port}), " + f"{next_kmd_port} (was {kmd_port}), {next_indexer_port} (was {indexer_port})" + ) + return forward_ports_for_codespace( + codespace_name, + next_algod_port if algod_port in occupied_ports else algod_port, + next_kmd_port if kmd_port in occupied_ports else kmd_port, + next_indexer_port if indexer_port in occupied_ports else indexer_port, + max_retries=max_retries, + timeout=timeout, + ) + return None + + initial_timestamp = time.time() + for attempt in reversed(range(1, max_retries + 1)): + new_timeout = timeout - (time.time() - initial_timestamp) + if new_timeout < 0: + raise subprocess.TimeoutExpired(cmd="gh codespace ports forward", timeout=timeout) + if _try_forward_ports_once(ports, codespace_name, int(new_timeout)): + logger.info("Port forwarding successful.") + break + logger.error("Port forwarding failed!") + if attempt > 1: + run_with_animation( + time.sleep, f"Retrying ({attempt - 1} attempts left)...", CODESPACE_PORT_FORWARD_RETRY_SECONDS + ) + else: + raise Exception( + "Port forwarding failed! Make sure you are not already running a localnet container on those ports." + ) + + +def delete_codespaces_with_prefix(codespaces: list[str], default_name: str) -> None: + """ + Deletes GitHub Codespaces that start with the specified default name. + + Args: + codespaces (list[str]): List of codespace names. + default_name (str): The prefix to match for deletion. + """ + for codespace in filter(lambda cs: cs.startswith(default_name), codespaces): + proc.run(["gh", "codespace", "delete", "--codespace", codespace, "--force"], pass_stdin=True) + logger.info(f"Deleted unused codespace {codespace}") + + +def is_codespace_ready(codespace_name: str) -> dict[str, Any]: + """ + Checks if the specified codespace is ready. + + Args: + codespace_name (str): The name of the codespace to check. + + Returns: + dict[str, Any] | None: The codespace data if ready, None otherwise. + """ + max_retries = 10 + while max_retries > 0: + max_retries -= 1 + + status_result = proc.run( + ["gh", "codespace", "list", "--json", "displayName", "--json", "state", "--json", "name"], + pass_stdin=True, + ) + try: + codespace_data: dict[str, Any] = next( + data for data in json.loads(status_result.output.strip()) if data["displayName"] == codespace_name + ) + except StopIteration: + run_with_animation( + time.sleep, + CODESPACE_LOADING_MSG, + CODESPACE_CREATE_RETRY_TIMEOUT, + ) + continue + + if status_result.exit_code == 0 and codespace_data and codespace_data["state"] == CODESPACE_CONTAINER_AVAILABLE: + return codespace_data + raise RuntimeError( + "After 10 attempts, codespace isn't ready. Avoid codespace deletion and retry with --codespace-name." + ) + + +def delete_codespace(*, codespace_data: dict[str, Any], force: bool) -> None: + """ + Deletes the specified codespace. + + Args: + codespace_data (dict[str, Any]): The codespace data. + force (bool): Whether to force deletion without confirmation. + """ + if codespace_data and (force or questionary_extensions.prompt_confirm("Delete the codespace?", default=True)): + logger.warning(f"Deleting the `{codespace_data['name']}` codespace...") + proc.run( + ["gh", "codespace", "delete", "--codespace", codespace_data["name"], "--force"], + pass_stdin=True, + ) + + +def create_codespace(repo_url: str, codespace_name: str, machine: str, timeout: int) -> None: + """ + Creates a GitHub Codespace with the specified repository, display name, and machine type. + + Args: + repo_url (str): The URL of the repository for the codespace. + codespace_name (str): The display name for the codespace. + machine (str): The machine type for the codespace. + """ + response = proc.run( + [ + "gh", + "codespace", + "create", + "--repo", + repo_url, + "--display-name", + codespace_name, + "--machine", + machine, + "--idle-timeout", + f"{timeout}m", + ], + pass_stdin=True, + ) + if response.exit_code != 0 and CODESPACE_TOO_MANY_ERROR_MSG in response.output.lower(): + raise Exception( + "Creation failed: User's codespace limit reached. Delete unused codespaces using `gh` cli and try again." + ) + + run_with_animation( + time.sleep, + CODESPACE_LOADING_MSG, + CODESPACE_CREATE_TIMEOUT, + ) diff --git a/src/algokit/core/config_commands/__init__.py b/src/algokit/core/config_commands/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/algokit/core/config_commands/container_engine.py b/src/algokit/core/config_commands/container_engine.py new file mode 100644 index 00000000..3c639f0e --- /dev/null +++ b/src/algokit/core/config_commands/container_engine.py @@ -0,0 +1,76 @@ +import enum +import logging + +import click +import questionary + +from algokit.core.conf import get_app_config_dir + +logger = logging.getLogger(__name__) + +CONTAINER_ENGINE_CONFIG_FILE = get_app_config_dir() / "active-container-engine" + + +class ContainerEngine(str, enum.Enum): + DOCKER = "docker" + PODMAN = "podman" + + def __str__(self) -> str: + return self.value + + +def get_container_engine() -> str: + if CONTAINER_ENGINE_CONFIG_FILE.exists(): + return CONTAINER_ENGINE_CONFIG_FILE.read_text().strip() + return str(ContainerEngine.DOCKER) + + +def save_container_engine(engine: str) -> None: + if engine not in ContainerEngine: + raise ValueError(f"Invalid container engine: {engine}") + CONTAINER_ENGINE_CONFIG_FILE.write_text(engine) + + +@click.command("container-engine", short_help="Configure the container engine for AlgoKit LocalNet.") +@click.argument("engine", required=False, type=click.Choice(["docker", "podman"])) +@click.option( + "--force", + "-f", + is_flag=True, + required=False, + default=False, + type=click.BOOL, + help=("Skip confirmation prompts. " "Defaults to 'yes' to all prompts."), +) +def container_engine_configuration_command(*, engine: str | None, force: bool) -> None: + """Set the default container engine for use by AlgoKit CLI to run LocalNet images.""" + from algokit.core.sandbox import ComposeSandbox + + if engine is None: + current_engine = get_container_engine() + choices = [ + f"Docker {'(Active)' if current_engine == ContainerEngine.DOCKER else ''}".strip(), + f"Podman {'(Active)' if current_engine == ContainerEngine.PODMAN else ''}".strip(), + ] + engine = questionary.select("Which container engine do you prefer?", choices=choices).ask() + if engine is None: + raise click.ClickException("No valid container engine selected. Aborting...") + engine = engine.split()[0].lower() + + sandbox = ComposeSandbox.from_environment() + has_active_instance = sandbox is not None and ( + force + or click.confirm( + f"Detected active localnet instance, would you like to restart it with '{engine}'?", + default=True, + ) + ) + if sandbox and has_active_instance: + sandbox.down() + save_container_engine(engine) + sandbox.write_compose_file() + sandbox.up() + else: + save_container_engine(engine) + + logger.info(f"Container engine set to `{engine}`") diff --git a/src/algokit/core/version_prompt.py b/src/algokit/core/config_commands/version_prompt.py similarity index 100% rename from src/algokit/core/version_prompt.py rename to src/algokit/core/config_commands/version_prompt.py diff --git a/src/algokit/core/goal.py b/src/algokit/core/goal.py index 42abe48a..8b77a23a 100644 --- a/src/algokit/core/goal.py +++ b/src/algokit/core/goal.py @@ -4,6 +4,8 @@ from pathlib import Path, PurePath from algokit.core.conf import get_app_config_dir +from algokit.core.config_commands.container_engine import get_container_engine +from algokit.core.sandbox import ContainerEngine logger = logging.getLogger(__name__) @@ -13,7 +15,11 @@ def get_volume_mount_path_docker() -> Path: def get_volume_mount_path_local(directory_name: str) -> Path: - return get_app_config_dir().joinpath(directory_name, "goal_mount") + path = get_app_config_dir().joinpath(directory_name, "goal_mount") + if get_container_engine() == ContainerEngine.PODMAN: + # Pre create the directory to avoid permission issues + path.mkdir(parents=True, exist_ok=True) + return path filename_pattern = re.compile(r"^[\w\-\.]+\.\w+$") diff --git a/src/algokit/core/proc.py b/src/algokit/core/proc.py index 29229359..04d602bf 100644 --- a/src/algokit/core/proc.py +++ b/src/algokit/core/proc.py @@ -77,6 +77,7 @@ def run_interactive( cwd: Path | None = None, env: dict[str, str] | None = None, bad_return_code_error_message: str | None = None, + timeout: int | None = None, ) -> RunResult: """Wraps subprocess.run() as an user interactive session and also adds logging of the command being executed, but not the output @@ -86,7 +87,7 @@ def run_interactive( command_str = " ".join(command) logger.debug(f"Running '{command_str}' in '{cwd or Path.cwd()}'") - result = subprocess_run(command, cwd=cwd, env=env, check=False) + result = subprocess_run(command, cwd=cwd, env=env, check=False, timeout=timeout) if result.returncode == 0: logger.debug(f"'{command_str}' completed successfully", extra=EXTRA_EXCLUDE_FROM_CONSOLE) diff --git a/src/algokit/core/sandbox.py b/src/algokit/core/sandbox.py index 8c3d9db1..a1da0b5c 100644 --- a/src/algokit/core/sandbox.py +++ b/src/algokit/core/sandbox.py @@ -3,6 +3,7 @@ import enum import json import logging +import re import time from pathlib import Path from typing import Any, cast @@ -10,12 +11,25 @@ import httpx from algokit.core.conf import get_app_config_dir +from algokit.core.config_commands.container_engine import get_container_engine from algokit.core.proc import RunResult, run, run_interactive logger = logging.getLogger(__name__) DOCKER_COMPOSE_MINIMUM_VERSION = "2.5.0" -DEFAULT_NAME = "sandbox" +PODMAN_COMPOSE_MINIMUM_VERSION = "1.0.6" + + +SANDBOX_BASE_NAME = "sandbox" +CONTAINER_ENGINE_CONFIG_FILE = get_app_config_dir() / "active-container-engine" + + +class ContainerEngine(str, enum.Enum): + DOCKER = "docker" + PODMAN = "podman" + + def __str__(self) -> str: + return self.value class ComposeFileStatus(enum.Enum): @@ -24,9 +38,16 @@ class ComposeFileStatus(enum.Enum): OUT_OF_DATE = enum.auto() +def get_min_compose_version() -> str: + container_engine = get_container_engine() + return ( + DOCKER_COMPOSE_MINIMUM_VERSION if container_engine == ContainerEngine.DOCKER else PODMAN_COMPOSE_MINIMUM_VERSION + ) + + class ComposeSandbox: - def __init__(self, name: str = DEFAULT_NAME) -> None: - self.name = DEFAULT_NAME if name == DEFAULT_NAME else f"{DEFAULT_NAME}_{name}" + def __init__(self, name: str = SANDBOX_BASE_NAME) -> None: + self.name = SANDBOX_BASE_NAME if name == SANDBOX_BASE_NAME else f"{SANDBOX_BASE_NAME}_{name}" self.directory = get_app_config_dir() / self.name if not self.directory.exists(): logger.debug(f"The {self.name} directory does not exist yet; creating it") @@ -54,26 +75,54 @@ def algod_network_template_file_path(self) -> Path: @classmethod def from_environment(cls) -> ComposeSandbox | None: - run_results = run( - ["docker", "compose", "ls", "--format", "json", "--filter", "name=algokit_sandbox*"], - bad_return_code_error_message="Failed to list running LocalNet", - ) - if run_results.exit_code != 0: - return None try: - data = json.loads(run_results.output) - for item in data: - config_file = item.get("ConfigFiles").split(",")[0] - full_name = Path(config_file).parent.name - name = ( - full_name.replace(f"{DEFAULT_NAME}_", "") if full_name.startswith(f"{DEFAULT_NAME}_") else full_name - ) - return cls(name) - return None + run_results = run( + [get_container_engine(), "compose", "ls", "--format", "json", "--filter", "name=algokit_sandbox*"], + bad_return_code_error_message="Failed to list running LocalNet", + ) + if run_results.exit_code != 0: + return None except Exception as err: + logger.debug(f"Error checking for existing sandbox: {err}", exc_info=True) + return None + + try: + json_lines = cls._extract_json_lines(run_results.output) + if not json_lines: + return None + + data = json.loads(json_lines[0]) + return cls._create_instance_from_data(data) + except (json.JSONDecodeError, KeyError, IndexError) as err: logger.info(f"Error checking config file: {err}", exc_info=True) return None + @staticmethod + def _extract_json_lines(output: str) -> list[str]: + valid_json_lines = [] + for line in output.splitlines(): + # strip ANSI color codes + parsed_line = re.sub(r"\x1b\[[0-9;]*[a-zA-Z]", "", line) + try: + json.loads(parsed_line) + valid_json_lines.append(parsed_line) + except json.JSONDecodeError: + continue + return valid_json_lines + + @classmethod + def _create_instance_from_data(cls, data: list[dict[str, Any]]) -> ComposeSandbox | None: + for item in data: + config_file = item.get("ConfigFiles", "").split(",")[0] + full_name = Path(config_file).parent.name + name = ( + full_name.replace(f"{SANDBOX_BASE_NAME}_", "") + if full_name.startswith(f"{SANDBOX_BASE_NAME}_") + else full_name + ) + return cls(name) + return None + def compose_file_status(self) -> ComposeFileStatus: try: compose_content = self.compose_file_path.read_text() @@ -108,7 +157,7 @@ def _run_compose_command( bad_return_code_error_message: str | None = None, ) -> RunResult: return run( - ["docker", "compose", *compose_args.split()], + [get_container_engine(), "compose", *compose_args.split()], cwd=self.directory, stdout_log_level=stdout_log_level, bad_return_code_error_message=bad_return_code_error_message, @@ -117,7 +166,8 @@ def _run_compose_command( def up(self) -> None: logger.info("Starting AlgoKit LocalNet now...") self._run_compose_command( - "up --detach --quiet-pull --wait", bad_return_code_error_message="Failed to start LocalNet" + f"up --detach --quiet-pull{' --wait' if get_container_engine() == ContainerEngine.DOCKER else ''}", + bad_return_code_error_message="Failed to start LocalNet", ) logger.debug("AlgoKit LocalNet started, waiting for health check") if _wait_for_algod(): @@ -147,7 +197,7 @@ def logs(self, *, follow: bool = False, no_color: bool = False, tail: str | None if tail is not None: compose_args += ["--tail", tail] run_interactive( - ["docker", "compose", *compose_args], + [get_container_engine(), "compose", *compose_args], cwd=self.directory, bad_return_code_error_message="Failed to get logs, are the containers running?", ) @@ -164,26 +214,23 @@ def ps(self, service_name: str | None = None) -> list[dict[str, Any]]: data = json.loads(run_results.output) # `docker compose ps --format json` on version >= 2.21.0 outputs seperate JSON objects, each on a new line else: - data = [json.loads(line) for line in run_results.output.splitlines() if line] + json_lines = self._extract_json_lines(run_results.output) + data = [json.loads(line) for line in json_lines] assert isinstance(data, list) return cast(list[dict[str, Any]], data) - def _get_local_image_version(self, image_name: str) -> str | None: + def _get_local_image_versions(self, image_name: str) -> list[str]: """ - Get the local version of a Docker image + Get the local versions of a Docker image. Note that a single image may be pulled from multiple repo digests. """ try: - arg = '{{index (split (index .RepoDigests 0) "@") 1}}' - local_version = run( - ["docker", "image", "inspect", image_name, "--format", arg], - cwd=self.directory, - bad_return_code_error_message="Failed to get image inspect", - ) - - return local_version.output.strip() - except Exception: - return None + arg = "{{range .RepoDigests}}{{println .}}{{end}}" + local_versions_output = run([get_container_engine(), "image", "inspect", image_name, "--format", arg]) + return [line.split("@")[1] if "@" in line else line for line in local_versions_output.output.splitlines()] + except Exception as e: + logger.debug(f"Failed to get local image versions: {e}", exc_info=True) + return [] def _get_latest_image_version(self, image_name: str) -> str | None: """ @@ -201,9 +248,9 @@ def _get_latest_image_version(self, image_name: str) -> str | None: return None def is_image_up_to_date(self, image_name: str) -> bool: - local_version = self._get_local_image_version(image_name) + local_versions = self._get_local_image_versions(image_name) latest_version = self._get_latest_image_version(image_name) - return local_version is None or latest_version is None or local_version == latest_version + return latest_version is None or latest_version in local_versions def check_docker_compose_for_new_image_versions(self) -> None: is_indexer_up_to_date = self.is_image_up_to_date(INDEXER_IMAGE) @@ -513,4 +560,4 @@ def fetch_indexer_status_data(service_info: dict[str, Any]) -> dict[str, Any]: return {"Status": "Error"} -DOCKER_COMPOSE_VERSION_COMMAND = ["docker", "compose", "version", "--format", "json"] +COMPOSE_VERSION_COMMAND = [get_container_engine(), "compose", "version", "--format", "json"] diff --git a/src/algokit/core/tasks/analyze.py b/src/algokit/core/tasks/analyze.py index 85387156..b1d2b9a7 100644 --- a/src/algokit/core/tasks/analyze.py +++ b/src/algokit/core/tasks/analyze.py @@ -85,7 +85,7 @@ def prepare_artifacts_folders(output_dir: Path | None) -> None: TEALER_DOT_FILES_ROOT.mkdir(parents=True, exist_ok=True) -def install_tealer_if_needed() -> None: +def ensure_tealer_installed() -> None: """ Install tealer if it's not already installed. """ diff --git a/src/algokit/core/utils.py b/src/algokit/core/utils.py index 41cb78e1..1da46f8e 100644 --- a/src/algokit/core/utils.py +++ b/src/algokit/core/utils.py @@ -1,4 +1,3 @@ -import codecs import os import platform import re @@ -8,7 +7,7 @@ import threading import time from collections.abc import Callable, Iterator -from concurrent.futures import ThreadPoolExecutor +from itertools import cycle from os import environ from pathlib import Path from shutil import which @@ -53,48 +52,37 @@ def is_network_available(host: str = "8.8.8.8", port: int = 53, timeout: float = def animate(name: str, stop_event: threading.Event) -> None: - spinner = { - "interval": 100, - "frames": SPINNER_FRAMES, - } - - while not stop_event.is_set(): - for frame in spinner["frames"]: # type: ignore # noqa: PGH003 - if stop_event.is_set(): - break - try: - text = codecs.decode(frame, "utf-8") - except Exception: - text = frame - output = f"\r{text} {name}" - sys.stdout.buffer.write(output.encode("utf-8")) - sys.stdout.buffer.write(CLEAR_LINE.encode("utf-8")) - sys.stdout.buffer.flush() - time.sleep(0.001 * spinner["interval"]) # type: ignore # noqa: PGH003 + """Displays an animated spinner in the console.""" + + for frame in cycle(SPINNER_FRAMES): + if stop_event.is_set(): + break + text = f"\r{frame} {name}" + sys.stdout.write(text) + sys.stdout.flush() + time.sleep(0.1) - sys.stdout.buffer.write(b"\r") - sys.stdout.buffer.write(b"\n") - sys.stdout.buffer.flush() + sys.stdout.write("\r" + CLEAR_LINE) # Clear the animation line + sys.stdout.flush() def run_with_animation( target_function: Callable[..., Any], animation_text: str = "Loading", *args: Any, **kwargs: Any ) -> Any: # noqa: ANN401 - with ThreadPoolExecutor(max_workers=2) as executor: - stop_event = threading.Event() - animation_future = executor.submit(animate, animation_text, stop_event) - function_future = executor.submit(target_function, *args, **kwargs) + """Executes a function while displaying an animation, handling termination.""" + stop_event = threading.Event() + animation_thread = threading.Thread(target=animate, args=(animation_text, stop_event), daemon=True) + animation_thread.start() - try: - result = function_future.result() - except Exception as e: - stop_event.set() - animation_future.result() - raise e - else: - stop_event.set() - animation_future.result() - return result + try: + result: Any = target_function(*args, **kwargs) + except Exception: + raise # Re-raise to propagate the exception + finally: + stop_event.set() + animation_thread.join() # Wait for animation to finish + + return result def find_valid_pipx_command(error_message: str) -> list[str]: diff --git a/tests/conftest.py b/tests/conftest.py index 8cf5e87e..95260ac4 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -225,6 +225,7 @@ def dummy_algokit_template_with_python_task(tmp_path_factory: pytest.TempPathFac @pytest.fixture(autouse=True) -def _clear_caches() -> None: +def _clear_caches(mocker: MockerFixture) -> None: get_project_dir_names_from_workspace.cache_clear() get_project_configs.cache_clear() + mocker.patch("algokit.core.config_commands.container_engine.get_container_engine", return_value="docker") diff --git a/tests/doctor/test_doctor.test_doctor_all_commands_not_found[linux].approved.txt b/tests/doctor/test_doctor.test_doctor_all_commands_not_found[linux].approved.txt index 9b42c43e..e42f875a 100644 --- a/tests/doctor/test_doctor.test_doctor_all_commands_not_found[linux].approved.txt +++ b/tests/doctor/test_doctor.test_doctor_all_commands_not_found[linux].approved.txt @@ -21,7 +21,7 @@ AlgoKit: 1.2.3 AlgoKit Python: 3.6.2 (location: /home/me/.local/pipx/venvs/algokit) OS: Linux-other-system-info docker: Command not found! - Docker required to run `algokit localnet` command; install via https://docs.docker.com/get-docker/ + `docker` required to run `algokit localnet` command; install via https://docker.io docker compose: Command not found! git: Command not found! Git required to run `algokit init`; install via https://github.com/git-guides/install-git diff --git a/tests/doctor/test_doctor.test_doctor_all_commands_not_found[macOS].approved.txt b/tests/doctor/test_doctor.test_doctor_all_commands_not_found[macOS].approved.txt index dd94e4f9..bb19a1e3 100644 --- a/tests/doctor/test_doctor.test_doctor_all_commands_not_found[macOS].approved.txt +++ b/tests/doctor/test_doctor.test_doctor_all_commands_not_found[macOS].approved.txt @@ -23,7 +23,7 @@ AlgoKit: 1.2.3 AlgoKit Python: 3.6.2 (location: /home/me/.local/pipx/venvs/algokit) OS: Darwin-other-system-info docker: Command not found! - Docker required to run `algokit localnet` command; install via https://docs.docker.com/get-docker/ + `docker` required to run `algokit localnet` command; install via https://docker.io docker compose: Command not found! git: Command not found! Git required to run `algokit init`; install via https://github.com/git-guides/install-git diff --git a/tests/doctor/test_doctor.test_doctor_all_commands_not_found[windows].approved.txt b/tests/doctor/test_doctor.test_doctor_all_commands_not_found[windows].approved.txt index 36405af2..89bcafc8 100644 --- a/tests/doctor/test_doctor.test_doctor_all_commands_not_found[windows].approved.txt +++ b/tests/doctor/test_doctor.test_doctor_all_commands_not_found[windows].approved.txt @@ -23,7 +23,7 @@ AlgoKit: 1.2.3 AlgoKit Python: 3.6.2 (location: /home/me/.local/pipx/venvs/algokit) OS: Windows-other-system-info docker: Command not found! - Docker required to run `algokit localnet` command; install via https://docs.docker.com/get-docker/ + `docker` required to run `algokit localnet` command; install via https://docker.io docker compose: Command not found! git: Command not found! Git required to `run algokit init`; install via `choco install git` if using Chocolatey, diff --git a/tests/doctor/test_doctor.test_doctor_with_docker_compose_version_warning.approved.txt b/tests/doctor/test_doctor.test_doctor_with_docker_compose_version_warning.approved.txt index dec056d6..7e65486f 100644 --- a/tests/doctor/test_doctor.test_doctor_with_docker_compose_version_warning.approved.txt +++ b/tests/doctor/test_doctor.test_doctor_with_docker_compose_version_warning.approved.txt @@ -28,7 +28,7 @@ OS: Darwin-other-system-info docker: 20.10.21 docker compose: 2.1.3 Docker Compose 2.5.0 required to run `algokit localnet` command; - install via https://docs.docker.com/compose/install/ + install via https://docker.io git: 2.37.1 python: 3.10.0 (location: /usr/local/bin/python) python3: 3.11.0 (location: /usr/local/bin/python3) diff --git a/tests/goal/test_goal.py b/tests/goal/test_goal.py index 5f519d4e..85bc9fb1 100644 --- a/tests/goal/test_goal.py +++ b/tests/goal/test_goal.py @@ -16,7 +16,7 @@ def _normalize_output(output: str) -> str: - return output.replace("\\", "/") + return output.replace("\\", "/").replace("docker", "{container_engine}").replace("podman", "{container_engine}") @pytest.fixture() diff --git a/tests/goal/test_goal.test_goal_complex_args.approved.txt b/tests/goal/test_goal.test_goal_complex_args.approved.txt index 0aeb030c..7ebac1e7 100644 --- a/tests/goal/test_goal.test_goal_complex_args.approved.txt +++ b/tests/goal/test_goal.test_goal_complex_args.approved.txt @@ -1,10 +1,10 @@ -DEBUG: Running 'docker version' in '{current_working_directory}' -DEBUG: docker: STDOUT -DEBUG: docker: STDERR -DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' -DEBUG: docker: [] -DEBUG: Running 'docker compose ps algod --format json' in '{app_config}/sandbox' -DEBUG: docker: [{"Name": "algokit_sandbox_algod", "State": "running"}] -DEBUG: Running 'docker exec --interactive --workdir /root algokit_sandbox_algod goal account export -a RKTAZY2ZLKUJBHDVVA3KKHEDK7PRVGIGOZAUUIZBNK2OEP6KQGEXKKUYUY' in '{current_working_directory}' +DEBUG: Running '{container_engine} version' in '{current_working_directory}' +DEBUG: {container_engine}: STDOUT +DEBUG: {container_engine}: STDERR +DEBUG: Running '{container_engine} compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' +DEBUG: {container_engine}: [] +DEBUG: Running '{container_engine} compose ps algod --format json' in '{app_config}/sandbox' +DEBUG: {container_engine}: [{"Name": "algokit_sandbox_algod", "State": "running"}] +DEBUG: Running '{container_engine} exec --interactive --workdir /root algokit_sandbox_algod goal account export -a RKTAZY2ZLKUJBHDVVA3KKHEDK7PRVGIGOZAUUIZBNK2OEP6KQGEXKKUYUY' in '{current_working_directory}' STDOUT STDERR diff --git a/tests/goal/test_goal.test_goal_compose_outdated.approved.txt b/tests/goal/test_goal.test_goal_compose_outdated.approved.txt index 5383e106..7d7a6ee4 100644 --- a/tests/goal/test_goal.test_goal_compose_outdated.approved.txt +++ b/tests/goal/test_goal.test_goal_compose_outdated.approved.txt @@ -1,6 +1,6 @@ -DEBUG: Running 'docker version' in '{current_working_directory}' -DEBUG: docker: STDOUT -DEBUG: docker: STDERR -DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' -DEBUG: docker: [] +DEBUG: Running '{container_engine} version' in '{current_working_directory}' +DEBUG: {container_engine}: STDOUT +DEBUG: {container_engine}: STDERR +DEBUG: Running '{container_engine} compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' +DEBUG: {container_engine}: [] Error: LocalNet definition is out of date; please run `algokit localnet reset` first! diff --git a/tests/goal/test_goal.test_goal_console.approved.txt b/tests/goal/test_goal.test_goal_console.approved.txt index 5e522675..99b14e5e 100644 --- a/tests/goal/test_goal.test_goal_console.approved.txt +++ b/tests/goal/test_goal.test_goal_console.approved.txt @@ -1,9 +1,9 @@ -DEBUG: Running 'docker version' in '{current_working_directory}' -DEBUG: docker: STDOUT -DEBUG: docker: STDERR -DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' -DEBUG: docker: [] -DEBUG: Running 'docker compose ps algod --format json' in '{app_config}/sandbox' -DEBUG: docker: [{"Name": "algokit_sandbox_algod", "State": "running"}] +DEBUG: Running '{container_engine} version' in '{current_working_directory}' +DEBUG: {container_engine}: STDOUT +DEBUG: {container_engine}: STDERR +DEBUG: Running '{container_engine} compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' +DEBUG: {container_engine}: [] +DEBUG: Running '{container_engine} compose ps algod --format json' in '{app_config}/sandbox' +DEBUG: {container_engine}: [{"Name": "algokit_sandbox_algod", "State": "running"}] Opening Bash console on the algod node; execute `exit` to return to original console -DEBUG: Running 'docker exec -it -w /root algokit_sandbox_algod bash' in '{current_working_directory}' +DEBUG: Running '{container_engine} exec -it -w /root algokit_sandbox_algod bash' in '{current_working_directory}' diff --git a/tests/goal/test_goal.test_goal_console_algod_not_created.approved.txt b/tests/goal/test_goal.test_goal_console_algod_not_created.approved.txt index b4d83650..312bc333 100644 --- a/tests/goal/test_goal.test_goal_console_algod_not_created.approved.txt +++ b/tests/goal/test_goal.test_goal_console_algod_not_created.approved.txt @@ -1,18 +1,18 @@ -DEBUG: Running 'docker version' in '{current_working_directory}' -DEBUG: docker: STDOUT -DEBUG: docker: STDERR -DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' -DEBUG: docker: [] -DEBUG: Running 'docker compose ps algod --format json' in '{app_config}/sandbox' -DEBUG: docker: [] +DEBUG: Running '{container_engine} version' in '{current_working_directory}' +DEBUG: {container_engine}: STDOUT +DEBUG: {container_engine}: STDERR +DEBUG: Running '{container_engine} compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' +DEBUG: {container_engine}: [] +DEBUG: Running '{container_engine} compose ps algod --format json' in '{app_config}/sandbox' +DEBUG: {container_engine}: [] LocalNet isn't running Starting AlgoKit LocalNet now... -DEBUG: Running 'docker compose up --detach --quiet-pull --wait' in '{app_config}/sandbox' -docker: STDOUT -docker: STDERR +DEBUG: Running '{container_engine} compose up --detach --quiet-pull --wait' in '{app_config}/sandbox' +{container_engine}: STDOUT +{container_engine}: STDERR DEBUG: AlgoKit LocalNet started, waiting for health check DEBUG: HTTP Request: GET http://localhost:4001/v2/status "HTTP/1.1 200 OK" DEBUG: AlgoKit LocalNet health check successful, algod is ready Started; execute `algokit explore` to explore LocalNet in a web user interface. Opening Bash console on the algod node; execute `exit` to return to original console -DEBUG: Running 'docker exec -it -w /root algokit_sandbox_algod bash' in '{current_working_directory}' +DEBUG: Running '{container_engine} exec -it -w /root algokit_sandbox_algod bash' in '{current_working_directory}' diff --git a/tests/goal/test_goal.test_goal_console_failed.approved.txt b/tests/goal/test_goal.test_goal_console_failed.approved.txt index 5e522675..99b14e5e 100644 --- a/tests/goal/test_goal.test_goal_console_failed.approved.txt +++ b/tests/goal/test_goal.test_goal_console_failed.approved.txt @@ -1,9 +1,9 @@ -DEBUG: Running 'docker version' in '{current_working_directory}' -DEBUG: docker: STDOUT -DEBUG: docker: STDERR -DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' -DEBUG: docker: [] -DEBUG: Running 'docker compose ps algod --format json' in '{app_config}/sandbox' -DEBUG: docker: [{"Name": "algokit_sandbox_algod", "State": "running"}] +DEBUG: Running '{container_engine} version' in '{current_working_directory}' +DEBUG: {container_engine}: STDOUT +DEBUG: {container_engine}: STDERR +DEBUG: Running '{container_engine} compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' +DEBUG: {container_engine}: [] +DEBUG: Running '{container_engine} compose ps algod --format json' in '{app_config}/sandbox' +DEBUG: {container_engine}: [{"Name": "algokit_sandbox_algod", "State": "running"}] Opening Bash console on the algod node; execute `exit` to return to original console -DEBUG: Running 'docker exec -it -w /root algokit_sandbox_algod bash' in '{current_working_directory}' +DEBUG: Running '{container_engine} exec -it -w /root algokit_sandbox_algod bash' in '{current_working_directory}' diff --git a/tests/goal/test_goal.test_goal_no_args.approved.txt b/tests/goal/test_goal.test_goal_no_args.approved.txt index 0eea483f..d0c77536 100644 --- a/tests/goal/test_goal.test_goal_no_args.approved.txt +++ b/tests/goal/test_goal.test_goal_no_args.approved.txt @@ -1,10 +1,10 @@ -DEBUG: Running 'docker version' in '{current_working_directory}' -DEBUG: docker: STDOUT -DEBUG: docker: STDERR -DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' -DEBUG: docker: [] -DEBUG: Running 'docker compose ps algod --format json' in '{app_config}/sandbox' -DEBUG: docker: [{"Name": "algokit_sandbox_algod", "State": "running"}] -DEBUG: Running 'docker exec --interactive --workdir /root algokit_sandbox_algod goal' in '{current_working_directory}' +DEBUG: Running '{container_engine} version' in '{current_working_directory}' +DEBUG: {container_engine}: STDOUT +DEBUG: {container_engine}: STDERR +DEBUG: Running '{container_engine} compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' +DEBUG: {container_engine}: [] +DEBUG: Running '{container_engine} compose ps algod --format json' in '{app_config}/sandbox' +DEBUG: {container_engine}: [{"Name": "algokit_sandbox_algod", "State": "running"}] +DEBUG: Running '{container_engine} exec --interactive --workdir /root algokit_sandbox_algod goal' in '{current_working_directory}' STDOUT STDERR diff --git a/tests/goal/test_goal.test_goal_simple_args.approved.txt b/tests/goal/test_goal.test_goal_simple_args.approved.txt index a683fc0b..a1e75a9e 100644 --- a/tests/goal/test_goal.test_goal_simple_args.approved.txt +++ b/tests/goal/test_goal.test_goal_simple_args.approved.txt @@ -1,10 +1,10 @@ -DEBUG: Running 'docker version' in '{current_working_directory}' -DEBUG: docker: STDOUT -DEBUG: docker: STDERR -DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' -DEBUG: docker: [] -DEBUG: Running 'docker compose ps algod --format json' in '{app_config}/sandbox' -DEBUG: docker: [{"Name": "algokit_sandbox_algod", "State": "running"}] -DEBUG: Running 'docker exec --interactive --workdir /root algokit_sandbox_algod goal account list' in '{current_working_directory}' +DEBUG: Running '{container_engine} version' in '{current_working_directory}' +DEBUG: {container_engine}: STDOUT +DEBUG: {container_engine}: STDERR +DEBUG: Running '{container_engine} compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' +DEBUG: {container_engine}: [] +DEBUG: Running '{container_engine} compose ps algod --format json' in '{app_config}/sandbox' +DEBUG: {container_engine}: [{"Name": "algokit_sandbox_algod", "State": "running"}] +DEBUG: Running '{container_engine} exec --interactive --workdir /root algokit_sandbox_algod goal account list' in '{current_working_directory}' STDOUT STDERR diff --git a/tests/goal/test_goal.test_goal_simple_args_on_named_localnet.approved.txt b/tests/goal/test_goal.test_goal_simple_args_on_named_localnet.approved.txt index bef0370f..9b101ec2 100644 --- a/tests/goal/test_goal.test_goal_simple_args_on_named_localnet.approved.txt +++ b/tests/goal/test_goal.test_goal_simple_args_on_named_localnet.approved.txt @@ -1,12 +1,12 @@ -DEBUG: Running 'docker version' in '{current_working_directory}' -DEBUG: docker: STDOUT -DEBUG: docker: STDERR -DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' -DEBUG: docker: [{"Name": "algokit_test", "Status": "running", "ConfigFiles": "to/test/docker-compose.yml"}] +DEBUG: Running '{container_engine} version' in '{current_working_directory}' +DEBUG: {container_engine}: STDOUT +DEBUG: {container_engine}: STDERR +DEBUG: Running '{container_engine} compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' +DEBUG: {container_engine}: [{"Name": "algokit_test", "Status": "running", "ConfigFiles": "to/test/{container_engine}-compose.yml"}] DEBUG: The sandbox_test directory does not exist yet; creating it A named LocalNet is running, goal command will be executed against the named LocalNet -DEBUG: Running 'docker compose ps algod --format json' in '{app_config}/sandbox_test' -DEBUG: docker: [{"Name": "algokit_sandbox_algod", "State": "running"}] -DEBUG: Running 'docker exec --interactive --workdir /root algokit_sandbox_test_algod goal account list' in '{current_working_directory}' +DEBUG: Running '{container_engine} compose ps algod --format json' in '{app_config}/sandbox_test' +DEBUG: {container_engine}: [{"Name": "algokit_sandbox_algod", "State": "running"}] +DEBUG: Running '{container_engine} exec --interactive --workdir /root algokit_sandbox_test_algod goal account list' in '{current_working_directory}' STDOUT STDERR diff --git a/tests/goal/test_goal.test_goal_simple_args_with_input_file.approved.txt b/tests/goal/test_goal.test_goal_simple_args_with_input_file.approved.txt index ad5b535a..de71067d 100644 --- a/tests/goal/test_goal.test_goal_simple_args_with_input_file.approved.txt +++ b/tests/goal/test_goal.test_goal_simple_args_with_input_file.approved.txt @@ -1,9 +1,9 @@ -DEBUG: Running 'docker version' in '{current_working_directory}' -DEBUG: docker: STDOUT -DEBUG: docker: STDERR -DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' -DEBUG: docker: [] -DEBUG: Running 'docker compose ps algod --format json' in '{app_config}/sandbox' -DEBUG: docker: [{"Name": "algokit_sandbox_algod", "State": "running"}] -DEBUG: Running 'docker exec --interactive --workdir /root algokit_sandbox_algod goal clerk group /root/goal_mount/transactions.txt' in '{current_working_directory}' +DEBUG: Running '{container_engine} version' in '{current_working_directory}' +DEBUG: {container_engine}: STDOUT +DEBUG: {container_engine}: STDERR +DEBUG: Running '{container_engine} compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' +DEBUG: {container_engine}: [] +DEBUG: Running '{container_engine} compose ps algod --format json' in '{app_config}/sandbox' +DEBUG: {container_engine}: [{"Name": "algokit_sandbox_algod", "State": "running"}] +DEBUG: Running '{container_engine} exec --interactive --workdir /root algokit_sandbox_algod goal clerk group /root/goal_mount/transactions.txt' in '{current_working_directory}' File compiled diff --git a/tests/goal/test_goal.test_goal_simple_args_with_input_output_files.approved.txt b/tests/goal/test_goal.test_goal_simple_args_with_input_output_files.approved.txt index 70905989..02c27e65 100644 --- a/tests/goal/test_goal.test_goal_simple_args_with_input_output_files.approved.txt +++ b/tests/goal/test_goal.test_goal_simple_args_with_input_output_files.approved.txt @@ -1,9 +1,9 @@ -DEBUG: Running 'docker version' in '{current_working_directory}' -DEBUG: docker: STDOUT -DEBUG: docker: STDERR -DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' -DEBUG: docker: [] -DEBUG: Running 'docker compose ps algod --format json' in '{app_config}/sandbox' -DEBUG: docker: [{"Name": "algokit_sandbox_algod", "State": "running"}] -DEBUG: Running 'docker exec --interactive --workdir /root algokit_sandbox_algod goal clerk compile /root/goal_mount/approval.teal -o /root/goal_mount/approval.compiled' in '{current_working_directory}' +DEBUG: Running '{container_engine} version' in '{current_working_directory}' +DEBUG: {container_engine}: STDOUT +DEBUG: {container_engine}: STDERR +DEBUG: Running '{container_engine} compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' +DEBUG: {container_engine}: [] +DEBUG: Running '{container_engine} compose ps algod --format json' in '{app_config}/sandbox' +DEBUG: {container_engine}: [{"Name": "algokit_sandbox_algod", "State": "running"}] +DEBUG: Running '{container_engine} exec --interactive --workdir /root algokit_sandbox_algod goal clerk compile /root/goal_mount/approval.teal -o /root/goal_mount/approval.compiled' in '{current_working_directory}' File compiled diff --git a/tests/goal/test_goal.test_goal_simple_args_with_input_output_files_with_dot_convention_name.approved.txt b/tests/goal/test_goal.test_goal_simple_args_with_input_output_files_with_dot_convention_name.approved.txt index 7e160fb7..ed3e777b 100644 --- a/tests/goal/test_goal.test_goal_simple_args_with_input_output_files_with_dot_convention_name.approved.txt +++ b/tests/goal/test_goal.test_goal_simple_args_with_input_output_files_with_dot_convention_name.approved.txt @@ -1,9 +1,9 @@ -DEBUG: Running 'docker version' in '{current_working_directory}' -DEBUG: docker: STDOUT -DEBUG: docker: STDERR -DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' -DEBUG: docker: [] -DEBUG: Running 'docker compose ps algod --format json' in '{app_config}/sandbox' -DEBUG: docker: [{"Name": "algokit_sandbox_algod", "State": "running"}] -DEBUG: Running 'docker exec --interactive --workdir /root algokit_sandbox_algod goal clerk compile /root/goal_mount/contract.approval.teal -o /root/goal_mount/approval.compiled' in '{current_working_directory}' +DEBUG: Running '{container_engine} version' in '{current_working_directory}' +DEBUG: {container_engine}: STDOUT +DEBUG: {container_engine}: STDERR +DEBUG: Running '{container_engine} compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' +DEBUG: {container_engine}: [] +DEBUG: Running '{container_engine} compose ps algod --format json' in '{app_config}/sandbox' +DEBUG: {container_engine}: [{"Name": "algokit_sandbox_algod", "State": "running"}] +DEBUG: Running '{container_engine} exec --interactive --workdir /root algokit_sandbox_algod goal clerk compile /root/goal_mount/contract.approval.teal -o /root/goal_mount/approval.compiled' in '{current_working_directory}' File compiled diff --git a/tests/goal/test_goal.test_goal_simple_args_with_multiple_input_output_files.approved.txt b/tests/goal/test_goal.test_goal_simple_args_with_multiple_input_output_files.approved.txt index f1ee712e..af2a993e 100644 --- a/tests/goal/test_goal.test_goal_simple_args_with_multiple_input_output_files.approved.txt +++ b/tests/goal/test_goal.test_goal_simple_args_with_multiple_input_output_files.approved.txt @@ -1,9 +1,9 @@ -DEBUG: Running 'docker version' in '{current_working_directory}' -DEBUG: docker: STDOUT -DEBUG: docker: STDERR -DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' -DEBUG: docker: [] -DEBUG: Running 'docker compose ps algod --format json' in '{app_config}/sandbox' -DEBUG: docker: [{"Name": "algokit_sandbox_algod", "State": "running"}] -DEBUG: Running 'docker exec --interactive --workdir /root algokit_sandbox_algod goal clerk compile /root/goal_mount/approval1.teal /root/goal_mount/approval2.teal -o /root/goal_mount/approval.compiled' in '{current_working_directory}' +DEBUG: Running '{container_engine} version' in '{current_working_directory}' +DEBUG: {container_engine}: STDOUT +DEBUG: {container_engine}: STDERR +DEBUG: Running '{container_engine} compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' +DEBUG: {container_engine}: [] +DEBUG: Running '{container_engine} compose ps algod --format json' in '{app_config}/sandbox' +DEBUG: {container_engine}: [{"Name": "algokit_sandbox_algod", "State": "running"}] +DEBUG: Running '{container_engine} exec --interactive --workdir /root algokit_sandbox_algod goal clerk compile /root/goal_mount/approval1.teal /root/goal_mount/approval2.teal -o /root/goal_mount/approval.compiled' in '{current_working_directory}' File compiled diff --git a/tests/goal/test_goal.test_goal_simple_args_with_output_file.approved.txt b/tests/goal/test_goal.test_goal_simple_args_with_output_file.approved.txt index 291d67e7..bba03025 100644 --- a/tests/goal/test_goal.test_goal_simple_args_with_output_file.approved.txt +++ b/tests/goal/test_goal.test_goal_simple_args_with_output_file.approved.txt @@ -1,9 +1,9 @@ -DEBUG: Running 'docker version' in '{current_working_directory}' -DEBUG: docker: STDOUT -DEBUG: docker: STDERR -DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' -DEBUG: docker: [] -DEBUG: Running 'docker compose ps algod --format json' in '{app_config}/sandbox' -DEBUG: docker: [{"Name": "algokit_sandbox_algod", "State": "running"}] -DEBUG: Running 'docker exec --interactive --workdir /root algokit_sandbox_algod goal account dump -o /root/goal_mount/balance_record.json' in '{current_working_directory}' +DEBUG: Running '{container_engine} version' in '{current_working_directory}' +DEBUG: {container_engine}: STDOUT +DEBUG: {container_engine}: STDERR +DEBUG: Running '{container_engine} compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' +DEBUG: {container_engine}: [] +DEBUG: Running '{container_engine} compose ps algod --format json' in '{app_config}/sandbox' +DEBUG: {container_engine}: [{"Name": "algokit_sandbox_algod", "State": "running"}] +DEBUG: Running '{container_engine} exec --interactive --workdir /root algokit_sandbox_algod goal account dump -o /root/goal_mount/balance_record.json' in '{current_working_directory}' File compiled diff --git a/tests/goal/test_goal.test_goal_simple_args_without_file_error.approved.txt b/tests/goal/test_goal.test_goal_simple_args_without_file_error.approved.txt index b5395800..408adb6e 100644 --- a/tests/goal/test_goal.test_goal_simple_args_without_file_error.approved.txt +++ b/tests/goal/test_goal.test_goal_simple_args_without_file_error.approved.txt @@ -1,8 +1,8 @@ -DEBUG: Running 'docker version' in '{current_working_directory}' -DEBUG: docker: STDOUT -DEBUG: docker: STDERR -DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' -DEBUG: docker: [] -DEBUG: Running 'docker compose ps algod --format json' in '{app_config}/sandbox' -DEBUG: docker: [{"Name": "algokit_sandbox_algod", "State": "running"}] +DEBUG: Running '{container_engine} version' in '{current_working_directory}' +DEBUG: {container_engine}: STDOUT +DEBUG: {container_engine}: STDERR +DEBUG: Running '{container_engine} compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' +DEBUG: {container_engine}: [] +DEBUG: Running '{container_engine} compose ps algod --format json' in '{app_config}/sandbox' +DEBUG: {container_engine}: [{"Name": "algokit_sandbox_algod", "State": "running"}] ERROR: approval.teal does not exist. diff --git a/tests/goal/test_goal.test_goal_start_without_docker.approved.txt b/tests/goal/test_goal.test_goal_start_without_docker.approved.txt index da357403..deefe77d 100644 --- a/tests/goal/test_goal.test_goal_start_without_docker.approved.txt +++ b/tests/goal/test_goal.test_goal_start_without_docker.approved.txt @@ -1,3 +1,3 @@ DEBUG: Running 'docker version' in '{current_working_directory}' -Error: Docker not found; please install Docker and add to path. -See https://docs.docker.com/get-docker/ for more information. +Error: docker not found; please install docker and add to path. +See https://www.docker.com/get-started/ for more information. diff --git a/tests/goal/test_goal.test_goal_start_without_docker_engine_running.approved.txt b/tests/goal/test_goal.test_goal_start_without_docker_engine_running.approved.txt index 2458d64a..63f0d36f 100644 --- a/tests/goal/test_goal.test_goal_start_without_docker_engine_running.approved.txt +++ b/tests/goal/test_goal.test_goal_start_without_docker_engine_running.approved.txt @@ -1,4 +1,4 @@ DEBUG: Running 'docker version' in '{current_working_directory}' DEBUG: docker: STDOUT DEBUG: docker: STDERR -Error: Docker engine isn't running; please start it. +Error: docker engine isn't running; please start it. diff --git a/tests/localnet/conftest.py b/tests/localnet/conftest.py index bf03051a..370dfa6f 100644 --- a/tests/localnet/conftest.py +++ b/tests/localnet/conftest.py @@ -21,15 +21,15 @@ def _health_success(httpx_mock: HTTPXMock) -> None: @pytest.fixture() def _localnet_up_to_date(proc_mock: ProcMock, httpx_mock: HTTPXMock) -> None: - arg = '{{index (split (index .RepoDigests 0) "@") 1}}' + arg = "{{range .RepoDigests}}{{println .}}{{end}}" proc_mock.set_output( ["docker", "image", "inspect", ALGORAND_IMAGE, "--format", arg], - ["sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"], + ["tag@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"], ) proc_mock.set_output( ["docker", "image", "inspect", INDEXER_IMAGE, "--format", arg], - ["sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"], + ["tag@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"], ) httpx_mock.add_response( diff --git a/tests/localnet/test_localnet.test_localnet_help.approved.txt b/tests/localnet/test_localnet.test_localnet_help.approved.txt index d7576cd0..fe56a0c3 100644 --- a/tests/localnet/test_localnet.test_localnet_help.approved.txt +++ b/tests/localnet/test_localnet.test_localnet_help.approved.txt @@ -4,12 +4,14 @@ Options: -h, --help Show this message and exit. Commands: - console Run the Algorand goal CLI against the AlgoKit LocalNet via a Bash - console so you can execute multiple goal commands and/or interact - with a filesystem. - explore Explore the AlgoKit LocalNet using Dappflow - logs See the output of the Docker containers - reset Reset the AlgoKit LocalNet. - start Start the AlgoKit LocalNet. - status Check the status of the AlgoKit LocalNet. - stop Stop the AlgoKit LocalNet. + codespace Manage the AlgoKit LocalNet in GitHub Codespaces. + config Configure the container engine for AlgoKit LocalNet. + console Run the Algorand goal CLI against the AlgoKit LocalNet via a Bash + console so you can execute multiple goal commands and/or interact + with a filesystem. + explore Explore the AlgoKit LocalNet using Dappflow + logs See the output of the Docker containers + reset Reset the AlgoKit LocalNet. + start Start the AlgoKit LocalNet. + status Check the status of the AlgoKit LocalNet. + stop Stop the AlgoKit LocalNet. diff --git a/tests/localnet/test_localnet_codespace.py b/tests/localnet/test_localnet_codespace.py new file mode 100644 index 00000000..774f7fe8 --- /dev/null +++ b/tests/localnet/test_localnet_codespace.py @@ -0,0 +1,138 @@ +import platform +from subprocess import CompletedProcess + +import pytest +from pytest_httpx import HTTPXMock +from pytest_mock import MockerFixture + +from tests.utils.approvals import verify +from tests.utils.click_invoker import invoke +from tests.utils.proc_mock import ProcMock + + +def test_install_gh_already_installed(mocker: MockerFixture, proc_mock: ProcMock) -> None: + proc_mock.set_output(["gh", "--version"], ["some version"]) + mocker.patch("algokit.cli.codespace.authenticate_with_github", return_value=False) + result = invoke("localnet codespace") + assert result.exit_code == 0 + + +def test_install_gh_not_installed_failed_install(mocker: MockerFixture, proc_mock: ProcMock) -> None: + proc_mock.should_fail_on(["gh", "--version"]) + mocker.patch("algokit.cli.codespace.authenticate_with_github", return_value=False) + mocker.patch("algokit.core.codespace.install_github_cli_via_webi", side_effect=RuntimeError("Failed to install gh")) + mocker.patch("algokit.core.codespace.is_windows", side_effect=RuntimeError("Failed to install gh")) + result = invoke("localnet codespace") + assert result.exit_code == 1 + verify(result.output) + + +@pytest.mark.mock_platform_system("Windows") +def test_install_gh_windows( + mocker: MockerFixture, proc_mock: ProcMock, tmp_path_factory: pytest.TempPathFactory +) -> None: + cwd = tmp_path_factory.mktemp("cwd") + dummy_script_path = cwd / "webi_dummy_installer.ps1" + dummy_script_path.touch() + + proc_mock.should_fail_on( + ["gh", "--version"], + ) + proc_mock.set_output( + ["powershell", "-command", "(Get-Variable PSVersionTable -ValueOnly).PSVersion"], ["PowerShell 7.2.1"] + ) + proc_mock.set_output( + [ + "powershell", + "-File", + str(dummy_script_path), + ], + ["installed gh!"], + ) + mocker.patch("algokit.cli.codespace.authenticate_with_github", return_value=False) + temp_file_mock = mocker.MagicMock() + temp_file_mock.__enter__.return_value.name = str(dummy_script_path) + mocker.patch("tempfile.NamedTemporaryFile", return_value=temp_file_mock) + + result = invoke("localnet codespace") + assert result.exit_code == 0 + + verify(result.output.replace(str(dummy_script_path), "{dummy_script_path}")) + + +@pytest.mark.skipif(platform.system().lower() == "windows", reason="Test only runs on Unix systems") +def test_install_gh_unix( + mocker: MockerFixture, proc_mock: ProcMock, httpx_mock: HTTPXMock, tmp_path_factory: pytest.TempPathFactory +) -> None: + cwd = tmp_path_factory.mktemp("cwd") + dummy_script_path = cwd / "webi_dummy_installer.sh" + dummy_script_path.touch() + proc_mock.set_output(["bash", "--version"], ["GNU bash, version 3.2.57(1)-release"]) + proc_mock.should_fail_on( + ["gh", "--version"], + ) + proc_mock.set_output(["bash", str(dummy_script_path)], ["installed gh!"]) + httpx_mock.add_response(url="https://webi.sh/gh", text="") + mocker.patch("algokit.cli.codespace.authenticate_with_github", return_value=False) + + temp_file_mock = mocker.MagicMock() + temp_file_mock.__enter__.return_value.name = str(cwd / "webi_dummy_installer.sh") + mocker.patch("tempfile.NamedTemporaryFile", return_value=temp_file_mock) + + result = invoke("localnet codespace") + assert result.exit_code == 0 + verify(result.output.replace(str(cwd), "{cwd}")) + + +def test_invalid_scope_auth( + mocker: MockerFixture, proc_mock: ProcMock, tmp_path_factory: pytest.TempPathFactory +) -> None: + cwd = tmp_path_factory.mktemp("cwd") + dummy_script_path = cwd / "webi_dummy_installer.sh" + dummy_script_path.touch() + proc_mock.set_output( + ["gh", "auth", "status"], + [ + """ + ✓ Logged in to github.com account aorumbayev (keyring) + - Active account: true + - Git operations protocol: https + - Token: gho_************************************ + - Token scopes: 'read:org', 'repo', 'workflow' +""" + ], + ) + mocker.patch("algokit.core.proc.subprocess_run").return_value = CompletedProcess( + args=["docker", "exec"], returncode=0, stdout="logged in!" + ) + proc_mock.set_output( + [ + "gh", + "codespace", + "create", + "--repo", + "algorandfoundation/algokit-base-template", + "--display-name", + "sandbox", + "--machine", + "basicLinux32gb", + ], + [], + ) + proc_mock.set_output( + ["gh", "codespace", "list", "--json", "displayName", "--json", "state", "--json", "name"], + [ + """ + [{"displayName":"sandbox","state":"Available","name":"sandbox"}] + """ + ], + ) + proc_mock.set_output( + ["gh", "codespace", "delete", "--codespace", "sandbox", "--force"], ["Deleted unused codespace"] + ) + mocker.patch("algokit.cli.codespace.forward_ports_for_codespace", return_value=None) + mocker.patch("algokit.core.codespace.run_with_animation") + + result = invoke("localnet codespace -n sandbox --force") + assert result.exit_code == 0 + verify(result.output) diff --git a/tests/localnet/test_localnet_codespace.test_install_gh_not_installed_failed_install.approved.txt b/tests/localnet/test_localnet_codespace.test_install_gh_not_installed_failed_install.approved.txt new file mode 100644 index 00000000..d73cb2e3 --- /dev/null +++ b/tests/localnet/test_localnet_codespace.test_install_gh_not_installed_failed_install.approved.txt @@ -0,0 +1,4 @@ +DEBUG: Running 'gh --version' in '{current_working_directory}' +Installing gh... +ERROR: Failed to automatically install gh cli: Failed to install gh +ERROR: Please install `gh cli` manually by following official documentation at https://cli.github.com/ diff --git a/tests/localnet/test_localnet_codespace.test_install_gh_unix.approved.txt b/tests/localnet/test_localnet_codespace.test_install_gh_unix.approved.txt new file mode 100644 index 00000000..9f3da359 --- /dev/null +++ b/tests/localnet/test_localnet_codespace.test_install_gh_unix.approved.txt @@ -0,0 +1,9 @@ +DEBUG: Running 'gh --version' in '{current_working_directory}' +Installing gh... +DEBUG: HTTP Request: GET https://webi.sh/gh "HTTP/1.1 200 OK" +DEBUG: Running 'bash --version' in '{current_working_directory}' +DEBUG: bash: GNU bash, version 3.2.57(1)-release +DEBUG: Running 'bash {cwd}/webi_dummy_installer.sh' in '{current_working_directory}' +DEBUG: bash: installed gh! +gh installed successfully! +WARNING: Restart your terminal to activate the `gh` CLI and re-run `algokit localnet codespace` to get started... diff --git a/tests/localnet/test_localnet_codespace.test_install_gh_windows.approved.txt b/tests/localnet/test_localnet_codespace.test_install_gh_windows.approved.txt new file mode 100644 index 00000000..855bc95a --- /dev/null +++ b/tests/localnet/test_localnet_codespace.test_install_gh_windows.approved.txt @@ -0,0 +1,9 @@ +DEBUG: Running 'gh --version' in '{current_working_directory}' +Installing gh... +DEBUG: HTTP Request: GET https://webi.ms/gh "HTTP/1.1 200 OK" +DEBUG: Running 'powershell -command (Get-Variable PSVersionTable -ValueOnly).PSVersion' in '{current_working_directory}' +DEBUG: powershell: PowerShell 7.2.1 +DEBUG: Running 'powershell -File {dummy_script_path}' in '{current_working_directory}' +DEBUG: powershell: installed gh! +gh installed successfully! +WARNING: Restart your terminal to activate the `gh` CLI and re-run `algokit localnet codespace` to get started... diff --git a/tests/localnet/test_localnet_codespace.test_invalid_scope_auth.approved.txt b/tests/localnet/test_localnet_codespace.test_invalid_scope_auth.approved.txt new file mode 100644 index 00000000..ac29a094 --- /dev/null +++ b/tests/localnet/test_localnet_codespace.test_invalid_scope_auth.approved.txt @@ -0,0 +1,26 @@ +DEBUG: Running 'gh --version' in '{current_working_directory}' +DEBUG: gh: STDOUT +DEBUG: gh: STDERR +DEBUG: Running 'gh auth status' in '{current_working_directory}' +DEBUG: gh: +DEBUG: gh: ✓ Logged in to github.com account aorumbayev (keyring) +DEBUG: gh: - Active account: true +DEBUG: gh: - Git operations protocol: https +DEBUG: gh: - Token: gho_************************************ +DEBUG: gh: - Token scopes: 'read:org', 'repo', 'workflow' +ERROR: Required 'codespace' scope is missing. Please ensure you have the 'codespace' scope by running `gh auth refresh-token -s codespace`. +DEBUG: Running 'gh auth login -s codespace' in '{current_working_directory}' +Logged in to GitHub Codespace +DEBUG: Running 'gh codespace create --repo algorandfoundation/algokit-base-template --display-name sandbox --machine basicLinux32gb --idle-timeout 240m' in '{current_working_directory}' +Waiting for codespace sandbox to be ready... +DEBUG: Running 'gh codespace list --json displayName --json state --json name' in '{current_working_directory}' +DEBUG: gh: +DEBUG: gh: [{"displayName":"sandbox","state":"Available","name":"sandbox"}] +DEBUG: gh: +Codespace sandbox is now ready. +WARNING: Keep the terminal open during the LocalNet session. Terminating the session will delete the codespace instance. +LocalNet started in GitHub Codespace +Exiting... +WARNING: Deleting the `sandbox` codespace... +DEBUG: Running 'gh codespace delete --codespace sandbox --force' in '{current_working_directory}' +DEBUG: gh: Deleted unused codespace diff --git a/tests/localnet/test_localnet_console.test_goal_console.approved.txt b/tests/localnet/test_localnet_console.test_goal_console.approved.txt index 7e9123e9..5762938d 100644 --- a/tests/localnet/test_localnet_console.test_goal_console.approved.txt +++ b/tests/localnet/test_localnet_console.test_goal_console.approved.txt @@ -1,16 +1,16 @@ -DEBUG: Running 'docker compose version --format json' in '{current_working_directory}' -DEBUG: docker: {"version": "v2.5.0"} -DEBUG: Running 'docker version' in '{current_working_directory}' -DEBUG: docker: STDOUT -DEBUG: docker: STDERR -DEBUG: Running 'docker version' in '{current_working_directory}' -DEBUG: docker: STDOUT -DEBUG: docker: STDERR -DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' -DEBUG: docker: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox_test/docker-compose.yml"}] +DEBUG: Running '{container_engine} compose version --format json' in '{current_working_directory}' +DEBUG: {container_engine}: {"version": "v2.5.0"} +DEBUG: Running '{container_engine} version' in '{current_working_directory}' +DEBUG: {container_engine}: STDOUT +DEBUG: {container_engine}: STDERR +DEBUG: Running '{container_engine} version' in '{current_working_directory}' +DEBUG: {container_engine}: STDOUT +DEBUG: {container_engine}: STDERR +DEBUG: Running '{container_engine} compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' +DEBUG: {container_engine}: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox_test/{container_engine}-compose.yml"}] DEBUG: The sandbox_test directory does not exist yet; creating it A named LocalNet is running, goal command will be executed against the named LocalNet -DEBUG: Running 'docker compose ps algod --format json' in '{app_config}/sandbox_test' -DEBUG: docker: [{"Name": "algokit_sandbox_algod", "State": "running"}] +DEBUG: Running '{container_engine} compose ps algod --format json' in '{app_config}/sandbox_test' +DEBUG: {container_engine}: [{"Name": "algokit_sandbox_algod", "State": "running"}] Opening Bash console on the algod node; execute `exit` to return to original console -DEBUG: Running 'docker exec -it -w /root algokit_sandbox_test_algod bash' in '{current_working_directory}' +DEBUG: Running '{container_engine} exec -it -w /root algokit_sandbox_test_algod bash' in '{current_working_directory}' diff --git a/tests/localnet/test_localnet_reset.test_localnet_reset_with_existing_sandbox_with_out_of_date_config.approved.txt b/tests/localnet/test_localnet_reset.test_localnet_reset_with_existing_sandbox_with_out_of_date_config.approved.txt index 06109624..5237acf5 100644 --- a/tests/localnet/test_localnet_reset.test_localnet_reset_with_existing_sandbox_with_out_of_date_config.approved.txt +++ b/tests/localnet/test_localnet_reset.test_localnet_reset_with_existing_sandbox_with_out_of_date_config.approved.txt @@ -10,11 +10,11 @@ DEBUG: Running 'docker compose down' in '{app_config}/sandbox' DEBUG: docker: STDOUT DEBUG: docker: STDERR LocalNet definition is out of date; updating it to latest -DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/indexer/tags/latest "HTTP/1.1 200 OK" -DEBUG: Running 'docker image inspect algorand/algod:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +DEBUG: Running 'docker image inspect algorand/algod:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/algod/tags/latest "HTTP/1.1 200 OK" Starting AlgoKit LocalNet now... DEBUG: Running 'docker compose up --detach --quiet-pull --wait' in '{app_config}/sandbox' diff --git a/tests/localnet/test_localnet_reset.test_localnet_reset_with_existing_sandbox_with_up_to_date_config.approved.txt b/tests/localnet/test_localnet_reset.test_localnet_reset_with_existing_sandbox_with_up_to_date_config.approved.txt index 71740e38..f3274973 100644 --- a/tests/localnet/test_localnet_reset.test_localnet_reset_with_existing_sandbox_with_up_to_date_config.approved.txt +++ b/tests/localnet/test_localnet_reset.test_localnet_reset_with_existing_sandbox_with_up_to_date_config.approved.txt @@ -9,11 +9,11 @@ Cleaning up the running AlgoKit LocalNet... DEBUG: Running 'docker compose down' in '{app_config}/sandbox' DEBUG: docker: STDOUT DEBUG: docker: STDERR -DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/indexer/tags/latest "HTTP/1.1 200 OK" -DEBUG: Running 'docker image inspect algorand/algod:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +DEBUG: Running 'docker image inspect algorand/algod:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/algod/tags/latest "HTTP/1.1 200 OK" Starting AlgoKit LocalNet now... DEBUG: Running 'docker compose up --detach --quiet-pull --wait' in '{app_config}/sandbox' diff --git a/tests/localnet/test_localnet_reset.test_localnet_reset_without_docker.approved.txt b/tests/localnet/test_localnet_reset.test_localnet_reset_without_docker.approved.txt index 98a41002..1723f767 100644 --- a/tests/localnet/test_localnet_reset.test_localnet_reset_without_docker.approved.txt +++ b/tests/localnet/test_localnet_reset.test_localnet_reset_without_docker.approved.txt @@ -1,3 +1,2 @@ DEBUG: Running 'docker compose version --format json' in '{current_working_directory}' -Error: Docker not found; please install Docker and add to path. -See https://docs.docker.com/get-docker/ for more information. +Error: Container engine not found; please install Docker or Podman and add to path. diff --git a/tests/localnet/test_localnet_reset.test_localnet_reset_without_docker_compose.approved.txt b/tests/localnet/test_localnet_reset.test_localnet_reset_without_docker_compose.approved.txt index 7cc7ddf7..248f417f 100644 --- a/tests/localnet/test_localnet_reset.test_localnet_reset_without_docker_compose.approved.txt +++ b/tests/localnet/test_localnet_reset.test_localnet_reset_without_docker_compose.approved.txt @@ -1,5 +1,4 @@ DEBUG: Running 'docker compose version --format json' in '{current_working_directory}' DEBUG: docker: STDOUT DEBUG: docker: STDERR -Error: Docker Compose not found; please install Docker Compose and add to path. -See https://docs.docker.com/compose/install/ for more information. +Error: Container engine compose not found; please install Docker Compose or Podman Compose and add to path. diff --git a/tests/localnet/test_localnet_reset.test_localnet_reset_without_docker_engine_running.approved.txt b/tests/localnet/test_localnet_reset.test_localnet_reset_without_docker_engine_running.approved.txt index 23130d77..73d8f51b 100644 --- a/tests/localnet/test_localnet_reset.test_localnet_reset_without_docker_engine_running.approved.txt +++ b/tests/localnet/test_localnet_reset.test_localnet_reset_without_docker_engine_running.approved.txt @@ -3,4 +3,4 @@ DEBUG: docker: {"version": "v2.5.0"} DEBUG: Running 'docker version' in '{current_working_directory}' DEBUG: docker: STDOUT DEBUG: docker: STDERR -Error: Docker engine isn't running; please start it. +Error: Container engine isn't running; please start it. diff --git a/tests/localnet/test_localnet_start.py b/tests/localnet/test_localnet_start.py index 195df0b2..57e8eaba 100644 --- a/tests/localnet/test_localnet_start.py +++ b/tests/localnet/test_localnet_start.py @@ -21,15 +21,15 @@ @pytest.fixture() def _localnet_out_of_date(proc_mock: ProcMock, httpx_mock: HTTPXMock) -> None: - arg = '{{index (split (index .RepoDigests 0) "@") 1}}' + arg = "{{range .RepoDigests}}{{println .}}{{end}}" proc_mock.set_output( ["docker", "image", "inspect", ALGORAND_IMAGE, "--format", arg], - ["sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"], + ["tag@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"], ) proc_mock.set_output( ["docker", "image", "inspect", INDEXER_IMAGE, "--format", arg], - ["sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"], + ["tag@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"], ) httpx_mock.add_response( @@ -49,7 +49,7 @@ def _localnet_out_of_date(proc_mock: ProcMock, httpx_mock: HTTPXMock) -> None: @pytest.fixture() def _localnet_img_check_cmd_error(proc_mock: ProcMock) -> None: - arg = '{{index (split (index .RepoDigests 0) "@") 1}}' + arg = "{{range .RepoDigests}}{{println .}}{{end}}" proc_mock.should_fail_on(["docker", "image", "inspect", ALGORAND_IMAGE, "--format", arg]) proc_mock.should_fail_on(["docker", "image", "inspect", INDEXER_IMAGE, "--format", arg]) diff --git a/tests/localnet/test_localnet_start.test_localnet_img_check_cmd_error.approved.txt b/tests/localnet/test_localnet_start.test_localnet_img_check_cmd_error.approved.txt index 6da5fec3..699bca4d 100644 --- a/tests/localnet/test_localnet_start.test_localnet_img_check_cmd_error.approved.txt +++ b/tests/localnet/test_localnet_start.test_localnet_img_check_cmd_error.approved.txt @@ -6,10 +6,12 @@ DEBUG: docker: STDERR DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' DEBUG: docker: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox/docker-compose.yml"}] DEBUG: The sandbox directory does not exist yet; creating it -DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' +DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: Failed to get local image versions: No such file or directory: docker DEBUG: Error checking image status: No response can be found for GET request on https://registry.hub.docker.com/v2/repositories/algorand/indexer/tags/latest amongst: Match all requests on http://localhost:4001/v2/status -DEBUG: Running 'docker image inspect algorand/algod:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' +DEBUG: Running 'docker image inspect algorand/algod:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: Failed to get local image versions: No such file or directory: docker DEBUG: Error checking image status: No response can be found for GET request on https://registry.hub.docker.com/v2/repositories/algorand/algod/tags/latest amongst: Match all requests on http://localhost:4001/v2/status DEBUG: LocalNet compose file does not exist yet; writing it out for the first time diff --git a/tests/localnet/test_localnet_start.test_localnet_start.approved.txt b/tests/localnet/test_localnet_start.test_localnet_start.approved.txt index 5d07b203..58113e6d 100644 --- a/tests/localnet/test_localnet_start.test_localnet_start.approved.txt +++ b/tests/localnet/test_localnet_start.test_localnet_start.approved.txt @@ -6,11 +6,11 @@ DEBUG: docker: STDERR DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' DEBUG: docker: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox/docker-compose.yml"}] DEBUG: The sandbox directory does not exist yet; creating it -DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/indexer/tags/latest "HTTP/1.1 200 OK" -DEBUG: Running 'docker image inspect algorand/algod:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +DEBUG: Running 'docker image inspect algorand/algod:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/algod/tags/latest "HTTP/1.1 200 OK" DEBUG: LocalNet compose file does not exist yet; writing it out for the first time Starting AlgoKit LocalNet now... diff --git a/tests/localnet/test_localnet_start.test_localnet_start_failure.approved.txt b/tests/localnet/test_localnet_start.test_localnet_start_failure.approved.txt index 9734b649..953ee4fd 100644 --- a/tests/localnet/test_localnet_start.test_localnet_start_failure.approved.txt +++ b/tests/localnet/test_localnet_start.test_localnet_start_failure.approved.txt @@ -6,11 +6,11 @@ DEBUG: docker: STDERR DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' DEBUG: docker: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox/docker-compose.yml"}] DEBUG: The sandbox directory does not exist yet; creating it -DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/indexer/tags/latest "HTTP/1.1 200 OK" -DEBUG: Running 'docker image inspect algorand/algod:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +DEBUG: Running 'docker image inspect algorand/algod:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/algod/tags/latest "HTTP/1.1 200 OK" DEBUG: LocalNet compose file does not exist yet; writing it out for the first time Starting AlgoKit LocalNet now... diff --git a/tests/localnet/test_localnet_start.test_localnet_start_health_bad_status.approved.txt b/tests/localnet/test_localnet_start.test_localnet_start_health_bad_status.approved.txt index 4b23c02d..3fe0125d 100644 --- a/tests/localnet/test_localnet_start.test_localnet_start_health_bad_status.approved.txt +++ b/tests/localnet/test_localnet_start.test_localnet_start_health_bad_status.approved.txt @@ -6,11 +6,11 @@ DEBUG: docker: STDERR DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' DEBUG: docker: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox/docker-compose.yml"}] DEBUG: The sandbox directory does not exist yet; creating it -DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/indexer/tags/latest "HTTP/1.1 200 OK" -DEBUG: Running 'docker image inspect algorand/algod:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +DEBUG: Running 'docker image inspect algorand/algod:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/algod/tags/latest "HTTP/1.1 200 OK" DEBUG: LocalNet compose file does not exist yet; writing it out for the first time Starting AlgoKit LocalNet now... diff --git a/tests/localnet/test_localnet_start.test_localnet_start_health_failure.approved.txt b/tests/localnet/test_localnet_start.test_localnet_start_health_failure.approved.txt index f1ae3054..de815b4b 100644 --- a/tests/localnet/test_localnet_start.test_localnet_start_health_failure.approved.txt +++ b/tests/localnet/test_localnet_start.test_localnet_start_health_failure.approved.txt @@ -6,11 +6,11 @@ DEBUG: docker: STDERR DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' DEBUG: docker: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox/docker-compose.yml"}] DEBUG: The sandbox directory does not exist yet; creating it -DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/indexer/tags/latest "HTTP/1.1 200 OK" -DEBUG: Running 'docker image inspect algorand/algod:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +DEBUG: Running 'docker image inspect algorand/algod:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/algod/tags/latest "HTTP/1.1 200 OK" DEBUG: LocalNet compose file does not exist yet; writing it out for the first time Starting AlgoKit LocalNet now... diff --git a/tests/localnet/test_localnet_start.test_localnet_start_out_date.approved.txt b/tests/localnet/test_localnet_start.test_localnet_start_out_date.approved.txt index 38b49778..70a3c8c9 100644 --- a/tests/localnet/test_localnet_start.test_localnet_start_out_date.approved.txt +++ b/tests/localnet/test_localnet_start.test_localnet_start_out_date.approved.txt @@ -6,12 +6,12 @@ DEBUG: docker: STDERR DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' DEBUG: docker: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox/docker-compose.yml"}] DEBUG: The sandbox directory does not exist yet; creating it -DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/indexer/tags/latest "HTTP/1.1 200 OK" WARNING: indexer has a new version available, run `algokit localnet reset --update` to get the latest version -DEBUG: Running 'docker image inspect algorand/algod:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +DEBUG: Running 'docker image inspect algorand/algod:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/algod/tags/latest "HTTP/1.1 200 OK" WARNING: algod has a new version available, run `algokit localnet reset --update` to get the latest version DEBUG: LocalNet compose file does not exist yet; writing it out for the first time diff --git a/tests/localnet/test_localnet_start.test_localnet_start_out_of_date_definition.approved.txt b/tests/localnet/test_localnet_start.test_localnet_start_out_of_date_definition.approved.txt index 38cc4bb9..3681fd3b 100644 --- a/tests/localnet/test_localnet_start.test_localnet_start_out_of_date_definition.approved.txt +++ b/tests/localnet/test_localnet_start.test_localnet_start_out_of_date_definition.approved.txt @@ -5,11 +5,11 @@ DEBUG: docker: STDOUT DEBUG: docker: STDERR DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' DEBUG: docker: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox/docker-compose.yml"}] -DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/indexer/tags/latest "HTTP/1.1 200 OK" -DEBUG: Running 'docker image inspect algorand/algod:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +DEBUG: Running 'docker image inspect algorand/algod:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/algod/tags/latest "HTTP/1.1 200 OK" WARNING: LocalNet definition is out of date; please run `algokit localnet reset` Starting AlgoKit LocalNet now... diff --git a/tests/localnet/test_localnet_start.test_localnet_start_out_of_date_definition_and_missing_config.approved.txt b/tests/localnet/test_localnet_start.test_localnet_start_out_of_date_definition_and_missing_config.approved.txt index 75689fe0..bd48e103 100644 --- a/tests/localnet/test_localnet_start.test_localnet_start_out_of_date_definition_and_missing_config.approved.txt +++ b/tests/localnet/test_localnet_start.test_localnet_start_out_of_date_definition_and_missing_config.approved.txt @@ -5,11 +5,11 @@ DEBUG: docker: STDOUT DEBUG: docker: STDERR DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' DEBUG: docker: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox/docker-compose.yml"}] -DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/indexer/tags/latest "HTTP/1.1 200 OK" -DEBUG: Running 'docker image inspect algorand/algod:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +DEBUG: Running 'docker image inspect algorand/algod:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/algod/tags/latest "HTTP/1.1 200 OK" WARNING: LocalNet definition is out of date; please run `algokit localnet reset` Starting AlgoKit LocalNet now... diff --git a/tests/localnet/test_localnet_start.test_localnet_start_up_to_date_definition.approved.txt b/tests/localnet/test_localnet_start.test_localnet_start_up_to_date_definition.approved.txt index 1f36a02f..fe850bba 100644 --- a/tests/localnet/test_localnet_start.test_localnet_start_up_to_date_definition.approved.txt +++ b/tests/localnet/test_localnet_start.test_localnet_start_up_to_date_definition.approved.txt @@ -5,11 +5,11 @@ DEBUG: docker: STDOUT DEBUG: docker: STDERR DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' DEBUG: docker: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox/docker-compose.yml"}] -DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/indexer/tags/latest "HTTP/1.1 200 OK" -DEBUG: Running 'docker image inspect algorand/algod:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +DEBUG: Running 'docker image inspect algorand/algod:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/algod/tags/latest "HTTP/1.1 200 OK" DEBUG: LocalNet compose file does not require updating Starting AlgoKit LocalNet now... diff --git a/tests/localnet/test_localnet_start.test_localnet_start_with_gitpod_docker_compose_version.approved.txt b/tests/localnet/test_localnet_start.test_localnet_start_with_gitpod_docker_compose_version.approved.txt index a7f08159..290dd054 100644 --- a/tests/localnet/test_localnet_start.test_localnet_start_with_gitpod_docker_compose_version.approved.txt +++ b/tests/localnet/test_localnet_start.test_localnet_start_with_gitpod_docker_compose_version.approved.txt @@ -6,11 +6,11 @@ DEBUG: docker: STDERR DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' DEBUG: docker: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox/docker-compose.yml"}] DEBUG: The sandbox directory does not exist yet; creating it -DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/indexer/tags/latest "HTTP/1.1 200 OK" -DEBUG: Running 'docker image inspect algorand/algod:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +DEBUG: Running 'docker image inspect algorand/algod:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/algod/tags/latest "HTTP/1.1 200 OK" DEBUG: LocalNet compose file does not exist yet; writing it out for the first time Starting AlgoKit LocalNet now... diff --git a/tests/localnet/test_localnet_start.test_localnet_start_with_name.approved.txt b/tests/localnet/test_localnet_start.test_localnet_start_with_name.approved.txt index 0b798fdb..9c606eec 100644 --- a/tests/localnet/test_localnet_start.test_localnet_start_with_name.approved.txt +++ b/tests/localnet/test_localnet_start.test_localnet_start_with_name.approved.txt @@ -6,11 +6,11 @@ DEBUG: docker: STDERR DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' DEBUG: docker: [{"Name": "algokit_sandbox_test", "Status": "running", "ConfigFiles": "sandbox_test/docker-compose.yml"}] DEBUG: The sandbox_test directory does not exist yet; creating it -DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox_test' -DEBUG: docker: sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/indexer/tags/latest "HTTP/1.1 200 OK" -DEBUG: Running 'docker image inspect algorand/algod:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox_test' -DEBUG: docker: sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +DEBUG: Running 'docker image inspect algorand/algod:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/algod/tags/latest "HTTP/1.1 200 OK" DEBUG: LocalNet compose file does not exist yet; writing it out for the first time The named LocalNet configuration has been created in {app_config}/sandbox_test. diff --git a/tests/localnet/test_localnet_start.test_localnet_start_with_old_docker_compose_version.approved.txt b/tests/localnet/test_localnet_start.test_localnet_start_with_old_docker_compose_version.approved.txt index cfd92b23..7ea0d9f4 100644 --- a/tests/localnet/test_localnet_start.test_localnet_start_with_old_docker_compose_version.approved.txt +++ b/tests/localnet/test_localnet_start.test_localnet_start_with_old_docker_compose_version.approved.txt @@ -1,4 +1,4 @@ DEBUG: Running 'docker compose version --format json' in '{current_working_directory}' DEBUG: docker: {"version": "v2.2.1"} -Error: Minimum docker compose version supported: v2.5.0, installed = v2.2.1 -Please update your Docker install +Error: Minimum compose version supported: v2.5.0, installed = v2.2.1 +Please update your compose install diff --git a/tests/localnet/test_localnet_start.test_localnet_start_with_unparseable_docker_compose_version.approved.txt b/tests/localnet/test_localnet_start.test_localnet_start_with_unparseable_docker_compose_version.approved.txt index db14b7d9..8ea03b87 100644 --- a/tests/localnet/test_localnet_start.test_localnet_start_with_unparseable_docker_compose_version.approved.txt +++ b/tests/localnet/test_localnet_start.test_localnet_start_with_unparseable_docker_compose_version.approved.txt @@ -1,6 +1,6 @@ DEBUG: Running 'docker compose version --format json' in '{current_working_directory}' DEBUG: docker: {"version": "v2.5-dev123"} -WARNING: Unable to extract docker compose version from output: +WARNING: Unable to extract compose version from output: {"version": "v2.5-dev123"} Please ensure a minimum of compose v2.5.0 is used DEBUG: Running 'docker version' in '{current_working_directory}' @@ -9,11 +9,11 @@ DEBUG: docker: STDERR DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' DEBUG: docker: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox/docker-compose.yml"}] DEBUG: The sandbox directory does not exist yet; creating it -DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +DEBUG: Running 'docker image inspect algorand/indexer:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/indexer/tags/latest "HTTP/1.1 200 OK" -DEBUG: Running 'docker image inspect algorand/algod:latest --format {{index (split (index .RepoDigests 0) "@") 1}}' in '{app_config}/sandbox' -DEBUG: docker: sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +DEBUG: Running 'docker image inspect algorand/algod:latest --format {{range .RepoDigests}}{{println .}}{{end}}' in '{current_working_directory}' +DEBUG: docker: tag@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DEBUG: HTTP Request: GET https://registry.hub.docker.com/v2/repositories/algorand/algod/tags/latest "HTTP/1.1 200 OK" DEBUG: LocalNet compose file does not exist yet; writing it out for the first time Starting AlgoKit LocalNet now... diff --git a/tests/localnet/test_localnet_start.test_localnet_start_without_docker.approved.txt b/tests/localnet/test_localnet_start.test_localnet_start_without_docker.approved.txt index 98a41002..1723f767 100644 --- a/tests/localnet/test_localnet_start.test_localnet_start_without_docker.approved.txt +++ b/tests/localnet/test_localnet_start.test_localnet_start_without_docker.approved.txt @@ -1,3 +1,2 @@ DEBUG: Running 'docker compose version --format json' in '{current_working_directory}' -Error: Docker not found; please install Docker and add to path. -See https://docs.docker.com/get-docker/ for more information. +Error: Container engine not found; please install Docker or Podman and add to path. diff --git a/tests/localnet/test_localnet_start.test_localnet_start_without_docker_compose.approved.txt b/tests/localnet/test_localnet_start.test_localnet_start_without_docker_compose.approved.txt index 7cc7ddf7..248f417f 100644 --- a/tests/localnet/test_localnet_start.test_localnet_start_without_docker_compose.approved.txt +++ b/tests/localnet/test_localnet_start.test_localnet_start_without_docker_compose.approved.txt @@ -1,5 +1,4 @@ DEBUG: Running 'docker compose version --format json' in '{current_working_directory}' DEBUG: docker: STDOUT DEBUG: docker: STDERR -Error: Docker Compose not found; please install Docker Compose and add to path. -See https://docs.docker.com/compose/install/ for more information. +Error: Container engine compose not found; please install Docker Compose or Podman Compose and add to path. diff --git a/tests/localnet/test_localnet_start.test_localnet_start_without_docker_engine_running.approved.txt b/tests/localnet/test_localnet_start.test_localnet_start_without_docker_engine_running.approved.txt index 23130d77..73d8f51b 100644 --- a/tests/localnet/test_localnet_start.test_localnet_start_without_docker_engine_running.approved.txt +++ b/tests/localnet/test_localnet_start.test_localnet_start_without_docker_engine_running.approved.txt @@ -3,4 +3,4 @@ DEBUG: docker: {"version": "v2.5.0"} DEBUG: Running 'docker version' in '{current_working_directory}' DEBUG: docker: STDOUT DEBUG: docker: STDERR -Error: Docker engine isn't running; please start it. +Error: Container engine isn't running; please start it. diff --git a/tests/localnet/test_localnet_status.test_localnet_status_docker_error.approved.txt b/tests/localnet/test_localnet_status.test_localnet_status_docker_error.approved.txt index 3eec1168..484aa6f3 100644 --- a/tests/localnet/test_localnet_status.test_localnet_status_docker_error.approved.txt +++ b/tests/localnet/test_localnet_status.test_localnet_status_docker_error.approved.txt @@ -5,6 +5,8 @@ DEBUG: docker: STDOUT DEBUG: docker: STDERR DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' DEBUG: docker: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox/docker-compose.yml"}] +# container engine +Name: docker (change with `algokit config container-engine`) DEBUG: Running 'docker compose ps --format json' in '{app_config}/sandbox' DEBUG: docker: [{"ID": "e900c9dfe5e4676ca7fb3ac38cbee366ca5429ae447222282b64c059f5727a47", "Name": "algokit_algod", "Image": "algorand/algod:latest", "Command": "/node/run/run.sh", "Project": "algokit_sandbox", "Service": "algod", "Created": 1701664778, "State": "running", "Status": "", "Health": "", "ExitCode": 0, "Publishers": [{"URL": "", "TargetPort": 4160, "PublishedPort": 0, "Protocol": "tcp"}, {"URL": "0.0.0.0", "TargetPort": 7833, "PublishedPort": 4002, "Protocol": "tcp"}, {"URL": "0.0.0.0", "TargetPort": 8080, "PublishedPort": 4001, "Protocol": "tcp"}, {"URL": "", "TargetPort": 9100, "PublishedPort": 0, "Protocol": "tcp"}, {"URL": "0.0.0.0", "TargetPort": 9392, "PublishedPort": 9392, "Protocol": "tcp"}]}, {"ID": "2ba986bf8539527dbc1f2c3e9d8f83e834099ffea30d31f341691b172748464f", "Name": "algokit_conduit", "Image": "algorand/conduit:latest", "Command": "docker-entrypoint.sh", "Project": "algokit_sandbox", "Service": "conduit", "Created": 1701664778, "State": "running", "Status": "", "Health": "", "ExitCode": 0, "Publishers": []}, {"ID": "fa5b36dddbd112eb8b52ccd4de7db47c55ad49124b0483896a23f6727335cb3d", "Name": "algokit_sandbox-indexer-1", "Image": "algorand/indexer:latest", "Command": "docker-entrypoint.sh daemon --enable-all-parameters", "Project": "algokit_sandbox", "Service": "indexer", "Created": 1701664778, "State": "running", "Status": "", "Health": "", "ExitCode": 0, "Publishers": [{"URL": "0.0.0.0", "TargetPort": 8980, "PublishedPort": 8980, "Protocol": "tcp"}]}, {"ID": "f3a0bf6fe1e1fcbff96b88f39e30bcadab4c1792234c970d654b7a34fb71e1d7", "Name": "algokit_postgres", "Image": "postgres:13-alpine", "Command": "docker-entrypoint.sh postgres", "Project": "algokit_sandbox", "Service": "indexer-db", "Created": 1701664778, "State": "running", "Status": "", "Health": "", "ExitCode": 0, "Publishers": [{"URL": "0.0.0.0", "TargetPort": 5432, "PublishedPort": 5443, "Protocol": "tcp"}]}] DEBUG: HTTP Request: GET http://localhost:4001/v2/status "HTTP/1.1 200 OK" diff --git a/tests/localnet/test_localnet_status.test_localnet_status_failure.approved.txt b/tests/localnet/test_localnet_status.test_localnet_status_failure.approved.txt index cf5a98dc..057d736d 100644 --- a/tests/localnet/test_localnet_status.test_localnet_status_failure.approved.txt +++ b/tests/localnet/test_localnet_status.test_localnet_status_failure.approved.txt @@ -5,6 +5,8 @@ DEBUG: docker: STDOUT DEBUG: docker: STDERR DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' DEBUG: docker: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox/docker-compose.yml"}] +# container engine +Name: docker (change with `algokit config container-engine`) DEBUG: Running 'docker compose ps --format json' in '{app_config}/sandbox' DEBUG: docker: [] Error: LocalNet has not been initialized yet, please run 'algokit localnet start' diff --git a/tests/localnet/test_localnet_status.test_localnet_status_http_error.approved.txt b/tests/localnet/test_localnet_status.test_localnet_status_http_error.approved.txt index e4a0bde4..5414febd 100644 --- a/tests/localnet/test_localnet_status.test_localnet_status_http_error.approved.txt +++ b/tests/localnet/test_localnet_status.test_localnet_status_http_error.approved.txt @@ -5,6 +5,8 @@ DEBUG: docker: STDOUT DEBUG: docker: STDERR DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' DEBUG: docker: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox/docker-compose.yml"}] +# container engine +Name: docker (change with `algokit config container-engine`) DEBUG: Running 'docker compose ps --format json' in '{app_config}/sandbox' DEBUG: docker: [{"ID": "e900c9dfe5e4676ca7fb3ac38cbee366ca5429ae447222282b64c059f5727a47", "Name": "algokit_algod", "Image": "algorand/algod:latest", "Command": "/node/run/run.sh", "Project": "algokit_sandbox", "Service": "algod", "Created": 1701664778, "State": "running", "Status": "", "Health": "", "ExitCode": 0, "Publishers": [{"URL": "", "TargetPort": 4160, "PublishedPort": 0, "Protocol": "tcp"}, {"URL": "0.0.0.0", "TargetPort": 7833, "PublishedPort": 4002, "Protocol": "tcp"}, {"URL": "0.0.0.0", "TargetPort": 8080, "PublishedPort": 4001, "Protocol": "tcp"}, {"URL": "", "TargetPort": 9100, "PublishedPort": 0, "Protocol": "tcp"}, {"URL": "0.0.0.0", "TargetPort": 9392, "PublishedPort": 9392, "Protocol": "tcp"}]}, {"ID": "2ba986bf8539527dbc1f2c3e9d8f83e834099ffea30d31f341691b172748464f", "Name": "algokit_conduit", "Image": "algorand/conduit:latest", "Command": "docker-entrypoint.sh", "Project": "algokit_sandbox", "Service": "conduit", "Created": 1701664778, "State": "running", "Status": "", "Health": "", "ExitCode": 0, "Publishers": []}, {"ID": "fa5b36dddbd112eb8b52ccd4de7db47c55ad49124b0483896a23f6727335cb3d", "Name": "algokit_sandbox-indexer-1", "Image": "algorand/indexer:latest", "Command": "docker-entrypoint.sh daemon --enable-all-parameters", "Project": "algokit_sandbox", "Service": "indexer", "Created": 1701664778, "State": "running", "Status": "", "Health": "", "ExitCode": 0, "Publishers": [{"URL": "0.0.0.0", "TargetPort": 8980, "PublishedPort": 8980, "Protocol": "tcp"}]}, {"ID": "f3a0bf6fe1e1fcbff96b88f39e30bcadab4c1792234c970d654b7a34fb71e1d7", "Name": "algokit_postgres", "Image": "postgres:13-alpine", "Command": "docker-entrypoint.sh postgres", "Project": "algokit_sandbox", "Service": "indexer-db", "Created": 1701664778, "State": "running", "Status": "", "Health": "", "ExitCode": 0, "Publishers": [{"URL": "0.0.0.0", "TargetPort": 5432, "PublishedPort": 5443, "Protocol": "tcp"}]}] DEBUG: HTTP Request: GET http://localhost:4001/v2/status "HTTP/1.1 200 OK" diff --git a/tests/localnet/test_localnet_status.test_localnet_status_missing_service.approved.txt b/tests/localnet/test_localnet_status.test_localnet_status_missing_service.approved.txt index def8f6e4..749755cc 100644 --- a/tests/localnet/test_localnet_status.test_localnet_status_missing_service.approved.txt +++ b/tests/localnet/test_localnet_status.test_localnet_status_missing_service.approved.txt @@ -5,6 +5,8 @@ DEBUG: docker: STDOUT DEBUG: docker: STDERR DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' DEBUG: docker: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox/docker-compose.yml"}] +# container engine +Name: docker (change with `algokit config container-engine`) DEBUG: Running 'docker compose ps --format json' in '{app_config}/sandbox' DEBUG: docker: [{"ID": "00e93d3db91d964d1b2bcf444c938140dc6b43398380374eaac8510f45381973", "Name": "algokit_algod", "Command": "start.sh", "Project": "algokit_sandbox", "Service": "algod", "State": "running", "Health": "", "ExitCode": 0, "Publishers": [{"URL": "0.0.0.0", "TargetPort": 4001, "PublishedPort": 4001, "Protocol": "tcp"}, {"URL": "0.0.0.0", "TargetPort": 4002, "PublishedPort": 4002, "Protocol": "tcp"}, {"URL": "0.0.0.0", "TargetPort": 9392, "PublishedPort": 9392, "Protocol": "tcp"}]}, {"ID": "9e66aca1cd3542446e7b88f0701122a90f388308f7de0b57b6e2d843b3da9026", "Name": "algokit_postgres", "Command": "docker-entrypoint.sh postgres", "Project": "algokit_sandbox", "Service": "indexer-db", "State": "running", "Health": "", "ExitCode": 0, "Publishers": [{"URL": "", "TargetPort": 5432, "PublishedPort": 0, "Protocol": "tcp"}]}] Error: LocalNet has not been initialized yet, please run 'algokit localnet start' diff --git a/tests/localnet/test_localnet_status.test_localnet_status_no_existing_definition.approved.txt b/tests/localnet/test_localnet_status.test_localnet_status_no_existing_definition.approved.txt index ae8eaa8f..13eef326 100644 --- a/tests/localnet/test_localnet_status.test_localnet_status_no_existing_definition.approved.txt +++ b/tests/localnet/test_localnet_status.test_localnet_status_no_existing_definition.approved.txt @@ -6,6 +6,9 @@ DEBUG: docker: STDERR DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' DEBUG: docker: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox/docker-compose.yml"}] DEBUG: The sandbox directory does not exist yet; creating it +# container engine +Name: docker (change with `algokit config container-engine`) DEBUG: Running 'docker compose ps --format json' in '{app_config}/sandbox' DEBUG: docker: STDOUT DEBUG: docker: STDERR +Error: LocalNet has not been initialized yet, please run 'algokit localnet start' diff --git a/tests/localnet/test_localnet_status.test_localnet_status_service_not_started.approved.txt b/tests/localnet/test_localnet_status.test_localnet_status_service_not_started.approved.txt index 11f145b8..0b23209b 100644 --- a/tests/localnet/test_localnet_status.test_localnet_status_service_not_started.approved.txt +++ b/tests/localnet/test_localnet_status.test_localnet_status_service_not_started.approved.txt @@ -5,6 +5,8 @@ DEBUG: docker: STDOUT DEBUG: docker: STDERR DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' DEBUG: docker: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox/docker-compose.yml"}] +# container engine +Name: docker (change with `algokit config container-engine`) DEBUG: Running 'docker compose ps --format json' in '{app_config}/sandbox' DEBUG: docker: [{"ID": "e900c9dfe5e4676ca7fb3ac38cbee366ca5429ae447222282b64c059f5727a47", "Name": "algokit_algod", "Image": "algorand/algod:latest", "Command": "/node/run/run.sh", "Project": "algokit_sandbox", "Service": "algod", "Created": 1701664778, "State": "running", "Status": "", "Health": "", "ExitCode": 0, "Publishers": [{"URL": "", "TargetPort": 4160, "PublishedPort": 0, "Protocol": "tcp"}, {"URL": "0.0.0.0", "TargetPort": 7833, "PublishedPort": 4002, "Protocol": "tcp"}, {"URL": "0.0.0.0", "TargetPort": 8080, "PublishedPort": 4001, "Protocol": "tcp"}, {"URL": "", "TargetPort": 9100, "PublishedPort": 0, "Protocol": "tcp"}, {"URL": "0.0.0.0", "TargetPort": 9392, "PublishedPort": 9392, "Protocol": "tcp"}]}, {"ID": "2ba986bf8539527dbc1f2c3e9d8f83e834099ffea30d31f341691b172748464f", "Name": "algokit_conduit", "Image": "algorand/conduit:latest", "Command": "docker-entrypoint.sh", "Project": "algokit_sandbox", "Service": "conduit", "Created": 1701664778, "State": "running", "Status": "", "Health": "", "ExitCode": 0, "Publishers": []}, {"ID": "fa5b36dddbd112eb8b52ccd4de7db47c55ad49124b0483896a23f6727335cb3d", "Name": "algokit_sandbox-indexer-1", "Image": "algorand/indexer:latest", "Command": "docker-entrypoint.sh daemon --enable-all-parameters", "Project": "algokit_sandbox", "Service": "indexer", "Created": 1701664778, "State": "running", "Status": "", "Health": "", "ExitCode": 0, "Publishers": [{"URL": "0.0.0.0", "TargetPort": 8980, "PublishedPort": 8980, "Protocol": "tcp"}]}, {"ID": "f3a0bf6fe1e1fcbff96b88f39e30bcadab4c1792234c970d654b7a34fb71e1d7", "Name": "algokit_postgres", "Image": "postgres:13-alpine", "Command": "docker-entrypoint.sh postgres", "Project": "algokit_sandbox", "Service": "indexer-db", "Created": 1701664778, "State": "running", "Status": "", "Health": "", "ExitCode": 0, "Publishers": [{"URL": "0.0.0.0", "TargetPort": 5432, "PublishedPort": 5443, "Protocol": "tcp"}]}] DEBUG: Error checking algod status: No response can be found for GET request on http://localhost:4001/v2/status amongst: diff --git a/tests/localnet/test_localnet_status.test_localnet_status_successful.approved.txt b/tests/localnet/test_localnet_status.test_localnet_status_successful.approved.txt index 8819fc4a..507ca715 100644 --- a/tests/localnet/test_localnet_status.test_localnet_status_successful.approved.txt +++ b/tests/localnet/test_localnet_status.test_localnet_status_successful.approved.txt @@ -5,6 +5,8 @@ DEBUG: docker: STDOUT DEBUG: docker: STDERR DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' DEBUG: docker: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox/docker-compose.yml"}] +# container engine +Name: docker (change with `algokit config container-engine`) DEBUG: Running 'docker compose ps --format json' in '{app_config}/sandbox' DEBUG: docker: [{"ID": "e900c9dfe5e4676ca7fb3ac38cbee366ca5429ae447222282b64c059f5727a47", "Name": "algokit_algod", "Image": "algorand/algod:latest", "Command": "/node/run/run.sh", "Project": "algokit_sandbox", "Service": "algod", "Created": 1701664778, "State": "running", "Status": "", "Health": "", "ExitCode": 0, "Publishers": [{"URL": "", "TargetPort": 4160, "PublishedPort": 0, "Protocol": "tcp"}, {"URL": "0.0.0.0", "TargetPort": 7833, "PublishedPort": 4002, "Protocol": "tcp"}, {"URL": "0.0.0.0", "TargetPort": 8080, "PublishedPort": 4001, "Protocol": "tcp"}, {"URL": "", "TargetPort": 9100, "PublishedPort": 0, "Protocol": "tcp"}, {"URL": "0.0.0.0", "TargetPort": 9392, "PublishedPort": 9392, "Protocol": "tcp"}]}, {"ID": "2ba986bf8539527dbc1f2c3e9d8f83e834099ffea30d31f341691b172748464f", "Name": "algokit_conduit", "Image": "algorand/conduit:latest", "Command": "docker-entrypoint.sh", "Project": "algokit_sandbox", "Service": "conduit", "Created": 1701664778, "State": "running", "Status": "", "Health": "", "ExitCode": 0, "Publishers": []}, {"ID": "fa5b36dddbd112eb8b52ccd4de7db47c55ad49124b0483896a23f6727335cb3d", "Name": "algokit_sandbox-indexer-1", "Image": "algorand/indexer:latest", "Command": "docker-entrypoint.sh daemon --enable-all-parameters", "Project": "algokit_sandbox", "Service": "indexer", "Created": 1701664778, "State": "running", "Status": "", "Health": "", "ExitCode": 0, "Publishers": [{"URL": "0.0.0.0", "TargetPort": 8980, "PublishedPort": 8980, "Protocol": "tcp"}]}, {"ID": "f3a0bf6fe1e1fcbff96b88f39e30bcadab4c1792234c970d654b7a34fb71e1d7", "Name": "algokit_postgres", "Image": "postgres:13-alpine", "Command": "docker-entrypoint.sh postgres", "Project": "algokit_sandbox", "Service": "indexer-db", "Created": 1701664778, "State": "running", "Status": "", "Health": "", "ExitCode": 0, "Publishers": [{"URL": "0.0.0.0", "TargetPort": 5432, "PublishedPort": 5443, "Protocol": "tcp"}]}] DEBUG: HTTP Request: GET http://localhost:4001/v2/status "HTTP/1.1 200 OK" diff --git a/tests/localnet/test_localnet_status.test_localnet_status_unexpected_port.approved.txt b/tests/localnet/test_localnet_status.test_localnet_status_unexpected_port.approved.txt index 3eec1168..484aa6f3 100644 --- a/tests/localnet/test_localnet_status.test_localnet_status_unexpected_port.approved.txt +++ b/tests/localnet/test_localnet_status.test_localnet_status_unexpected_port.approved.txt @@ -5,6 +5,8 @@ DEBUG: docker: STDOUT DEBUG: docker: STDERR DEBUG: Running 'docker compose ls --format json --filter name=algokit_sandbox*' in '{current_working_directory}' DEBUG: docker: [{"Name": "algokit_sandbox", "Status": "running", "ConfigFiles": "test/sandbox/docker-compose.yml"}] +# container engine +Name: docker (change with `algokit config container-engine`) DEBUG: Running 'docker compose ps --format json' in '{app_config}/sandbox' DEBUG: docker: [{"ID": "e900c9dfe5e4676ca7fb3ac38cbee366ca5429ae447222282b64c059f5727a47", "Name": "algokit_algod", "Image": "algorand/algod:latest", "Command": "/node/run/run.sh", "Project": "algokit_sandbox", "Service": "algod", "Created": 1701664778, "State": "running", "Status": "", "Health": "", "ExitCode": 0, "Publishers": [{"URL": "", "TargetPort": 4160, "PublishedPort": 0, "Protocol": "tcp"}, {"URL": "0.0.0.0", "TargetPort": 7833, "PublishedPort": 4002, "Protocol": "tcp"}, {"URL": "0.0.0.0", "TargetPort": 8080, "PublishedPort": 4001, "Protocol": "tcp"}, {"URL": "", "TargetPort": 9100, "PublishedPort": 0, "Protocol": "tcp"}, {"URL": "0.0.0.0", "TargetPort": 9392, "PublishedPort": 9392, "Protocol": "tcp"}]}, {"ID": "2ba986bf8539527dbc1f2c3e9d8f83e834099ffea30d31f341691b172748464f", "Name": "algokit_conduit", "Image": "algorand/conduit:latest", "Command": "docker-entrypoint.sh", "Project": "algokit_sandbox", "Service": "conduit", "Created": 1701664778, "State": "running", "Status": "", "Health": "", "ExitCode": 0, "Publishers": []}, {"ID": "fa5b36dddbd112eb8b52ccd4de7db47c55ad49124b0483896a23f6727335cb3d", "Name": "algokit_sandbox-indexer-1", "Image": "algorand/indexer:latest", "Command": "docker-entrypoint.sh daemon --enable-all-parameters", "Project": "algokit_sandbox", "Service": "indexer", "Created": 1701664778, "State": "running", "Status": "", "Health": "", "ExitCode": 0, "Publishers": [{"URL": "0.0.0.0", "TargetPort": 8980, "PublishedPort": 8980, "Protocol": "tcp"}]}, {"ID": "f3a0bf6fe1e1fcbff96b88f39e30bcadab4c1792234c970d654b7a34fb71e1d7", "Name": "algokit_postgres", "Image": "postgres:13-alpine", "Command": "docker-entrypoint.sh postgres", "Project": "algokit_sandbox", "Service": "indexer-db", "Created": 1701664778, "State": "running", "Status": "", "Health": "", "ExitCode": 0, "Publishers": [{"URL": "0.0.0.0", "TargetPort": 5432, "PublishedPort": 5443, "Protocol": "tcp"}]}] DEBUG: HTTP Request: GET http://localhost:4001/v2/status "HTTP/1.1 200 OK" diff --git a/tests/localnet/test_localnet_status.test_localnet_status_without_docker.approved.txt b/tests/localnet/test_localnet_status.test_localnet_status_without_docker.approved.txt index 98a41002..1723f767 100644 --- a/tests/localnet/test_localnet_status.test_localnet_status_without_docker.approved.txt +++ b/tests/localnet/test_localnet_status.test_localnet_status_without_docker.approved.txt @@ -1,3 +1,2 @@ DEBUG: Running 'docker compose version --format json' in '{current_working_directory}' -Error: Docker not found; please install Docker and add to path. -See https://docs.docker.com/get-docker/ for more information. +Error: Container engine not found; please install Docker or Podman and add to path. diff --git a/tests/localnet/test_localnet_status.test_localnet_status_without_docker_compose.approved.txt b/tests/localnet/test_localnet_status.test_localnet_status_without_docker_compose.approved.txt index 7cc7ddf7..248f417f 100644 --- a/tests/localnet/test_localnet_status.test_localnet_status_without_docker_compose.approved.txt +++ b/tests/localnet/test_localnet_status.test_localnet_status_without_docker_compose.approved.txt @@ -1,5 +1,4 @@ DEBUG: Running 'docker compose version --format json' in '{current_working_directory}' DEBUG: docker: STDOUT DEBUG: docker: STDERR -Error: Docker Compose not found; please install Docker Compose and add to path. -See https://docs.docker.com/compose/install/ for more information. +Error: Container engine compose not found; please install Docker Compose or Podman Compose and add to path. diff --git a/tests/localnet/test_localnet_status.test_localnet_status_without_docker_engine_running.approved.txt b/tests/localnet/test_localnet_status.test_localnet_status_without_docker_engine_running.approved.txt index 23130d77..73d8f51b 100644 --- a/tests/localnet/test_localnet_status.test_localnet_status_without_docker_engine_running.approved.txt +++ b/tests/localnet/test_localnet_status.test_localnet_status_without_docker_engine_running.approved.txt @@ -3,4 +3,4 @@ DEBUG: docker: {"version": "v2.5.0"} DEBUG: Running 'docker version' in '{current_working_directory}' DEBUG: docker: STDOUT DEBUG: docker: STDERR -Error: Docker engine isn't running; please start it. +Error: Container engine isn't running; please start it. diff --git a/tests/localnet/test_localnet_stop.test_localnet_stop_without_docker.approved.txt b/tests/localnet/test_localnet_stop.test_localnet_stop_without_docker.approved.txt index 98a41002..1723f767 100644 --- a/tests/localnet/test_localnet_stop.test_localnet_stop_without_docker.approved.txt +++ b/tests/localnet/test_localnet_stop.test_localnet_stop_without_docker.approved.txt @@ -1,3 +1,2 @@ DEBUG: Running 'docker compose version --format json' in '{current_working_directory}' -Error: Docker not found; please install Docker and add to path. -See https://docs.docker.com/get-docker/ for more information. +Error: Container engine not found; please install Docker or Podman and add to path. diff --git a/tests/localnet/test_localnet_stop.test_localnet_stop_without_docker_compose.approved.txt b/tests/localnet/test_localnet_stop.test_localnet_stop_without_docker_compose.approved.txt index 7cc7ddf7..248f417f 100644 --- a/tests/localnet/test_localnet_stop.test_localnet_stop_without_docker_compose.approved.txt +++ b/tests/localnet/test_localnet_stop.test_localnet_stop_without_docker_compose.approved.txt @@ -1,5 +1,4 @@ DEBUG: Running 'docker compose version --format json' in '{current_working_directory}' DEBUG: docker: STDOUT DEBUG: docker: STDERR -Error: Docker Compose not found; please install Docker Compose and add to path. -See https://docs.docker.com/compose/install/ for more information. +Error: Container engine compose not found; please install Docker Compose or Podman Compose and add to path. diff --git a/tests/localnet/test_localnet_stop.test_localnet_stop_without_docker_engine_running.approved.txt b/tests/localnet/test_localnet_stop.test_localnet_stop_without_docker_engine_running.approved.txt index 23130d77..73d8f51b 100644 --- a/tests/localnet/test_localnet_stop.test_localnet_stop_without_docker_engine_running.approved.txt +++ b/tests/localnet/test_localnet_stop.test_localnet_stop_without_docker_engine_running.approved.txt @@ -3,4 +3,4 @@ DEBUG: docker: {"version": "v2.5.0"} DEBUG: Running 'docker version' in '{current_working_directory}' DEBUG: docker: STDOUT DEBUG: docker: STDERR -Error: Docker engine isn't running; please start it. +Error: Container engine isn't running; please start it. diff --git a/tests/tasks/TestIpfsUpload.test_ipfs_upload_http_error.approved.txt b/tests/tasks/TestIpfsUpload.test_ipfs_upload_http_error.approved.txt index 6aeff915..188f5a2e 100644 --- a/tests/tasks/TestIpfsUpload.test_ipfs_upload_http_error.approved.txt +++ b/tests/tasks/TestIpfsUpload.test_ipfs_upload_http_error.approved.txt @@ -1,3 +1,3 @@ -HTTP Request: POST https://api.pinata.cloud/pinning/pinFileToIPFS "HTTP/1.1 500 Internal Server Error" +DEBUG: HTTP Request: POST https://api.pinata.cloud/pinning/pinFileToIPFS "HTTP/1.1 500 Internal Server Error" DEBUG: Pinata error: 500. {"ok": false, "cid": "test"} Error: PinataInternalServerError('Pinata error: 500') diff --git a/tests/tasks/TestIpfsUpload.test_ipfs_upload_successful.approved.txt b/tests/tasks/TestIpfsUpload.test_ipfs_upload_successful.approved.txt index 5237b92c..fea1df41 100644 --- a/tests/tasks/TestIpfsUpload.test_ipfs_upload_successful.approved.txt +++ b/tests/tasks/TestIpfsUpload.test_ipfs_upload_successful.approved.txt @@ -1,3 +1,3 @@ -HTTP Request: POST https://api.pinata.cloud/pinning/pinFileToIPFS "HTTP/1.1 200 OK" +DEBUG: HTTP Request: POST https://api.pinata.cloud/pinning/pinFileToIPFS "HTTP/1.1 200 OK" File uploaded successfully! CID: test diff --git a/tests/tasks/test_analyze.test_analyze_diff_flag.approved.txt b/tests/tasks/test_analyze.test_analyze_diff_flag.approved.txt index af74a133..f4770f11 100644 --- a/tests/tasks/test_analyze.test_analyze_diff_flag.approved.txt +++ b/tests/tasks/test_analyze.test_analyze_diff_flag.approved.txt @@ -1,7 +1,7 @@ DEBUG: Running 'tealer --version' in '{current_working_directory}' DEBUG: tealer: 0.1.2 Warning: This task uses `tealer` to suggest improvements for your TEAL programs, but remember to always test your smart contracts code, follow modern software engineering practices and use the guidelines for smart contract development. This should not be used as a substitute for an actual audit. Do you understand? [Y/n]: y -Running 'tealer --json {current_working_directory}/dummy_report.json detect --contracts {current_working_directory}/dummy.teal' in '{current_working_directory}' -tealer: Reading contract from file: "{current_working_directory}/dummy.teal" -tealer: json output is written to {current_working_directory}/dummy_report.json +DEBUG: Running 'tealer --json {current_working_directory}/dummy_report.json detect --contracts {current_working_directory}/dummy.teal' in '{current_working_directory}' +DEBUG: tealer: Reading contract from file: "{current_working_directory}/dummy.teal" +DEBUG: tealer: json output is written to {current_working_directory}/dummy_report.json ERROR: Diff detected in {current_working_directory}/dummy.teal! Please check the content of the snapshot report {current_working_directory}/dummy_report.json against the latest received report at {current_working_directory}/dummy_report.received.json. diff --git a/tests/tasks/test_analyze.test_analyze_multiple_files.approved.txt b/tests/tasks/test_analyze.test_analyze_multiple_files.approved.txt index c991e773..62645093 100644 --- a/tests/tasks/test_analyze.test_analyze_multiple_files.approved.txt +++ b/tests/tasks/test_analyze.test_analyze_multiple_files.approved.txt @@ -1,21 +1,21 @@ DEBUG: Running 'tealer --version' in '{current_working_directory}' DEBUG: tealer: 0.1.2 Warning: This task uses `tealer` to suggest improvements for your TEAL programs, but remember to always test your smart contracts code, follow modern software engineering practices and use the guidelines for smart contract development. This should not be used as a substitute for an actual audit. Do you understand? [Y/n]: y -Running 'tealer --json {current_working_directory}/dummy_0.teal detect --contracts {current_working_directory}/dummy_contracts/dummy_0.teal' in '{current_working_directory}' -tealer: Reading contract from file: "{current_working_directory}/dummy_contracts/dummy_0.teal" -tealer: json output is written to {current_working_directory}/dummy_0.teal -Running 'tealer --json {current_working_directory}/dummy_1.teal detect --contracts {current_working_directory}/dummy_contracts/dummy_1.teal' in '{current_working_directory}' -tealer: Reading contract from file: "{current_working_directory}/dummy_contracts/dummy_1.teal" -tealer: json output is written to {current_working_directory}/dummy_1.teal -Running 'tealer --json {current_working_directory}/dummy_2.teal detect --contracts {current_working_directory}/dummy_contracts/dummy_2.teal' in '{current_working_directory}' -tealer: Reading contract from file: "{current_working_directory}/dummy_contracts/dummy_2.teal" -tealer: json output is written to {current_working_directory}/dummy_2.teal -Running 'tealer --json {current_working_directory}/dummy_3.teal detect --contracts {current_working_directory}/dummy_contracts/dummy_3.teal' in '{current_working_directory}' -tealer: Reading contract from file: "{current_working_directory}/dummy_contracts/dummy_3.teal" -tealer: json output is written to {current_working_directory}/dummy_3.teal -Running 'tealer --json {current_working_directory}/dummy_4.teal detect --contracts {current_working_directory}/dummy_contracts/dummy_4.teal' in '{current_working_directory}' -tealer: Reading contract from file: "{current_working_directory}/dummy_contracts/dummy_4.teal" -tealer: json output is written to {current_working_directory}/dummy_4.teal +DEBUG: Running 'tealer --json {current_working_directory}/dummy_0.teal detect --contracts {current_working_directory}/dummy_contracts/dummy_0.teal' in '{current_working_directory}' +DEBUG: tealer: Reading contract from file: "{current_working_directory}/dummy_contracts/dummy_0.teal" +DEBUG: tealer: json output is written to {current_working_directory}/dummy_0.teal +DEBUG: Running 'tealer --json {current_working_directory}/dummy_1.teal detect --contracts {current_working_directory}/dummy_contracts/dummy_1.teal' in '{current_working_directory}' +DEBUG: tealer: Reading contract from file: "{current_working_directory}/dummy_contracts/dummy_1.teal" +DEBUG: tealer: json output is written to {current_working_directory}/dummy_1.teal +DEBUG: Running 'tealer --json {current_working_directory}/dummy_2.teal detect --contracts {current_working_directory}/dummy_contracts/dummy_2.teal' in '{current_working_directory}' +DEBUG: tealer: Reading contract from file: "{current_working_directory}/dummy_contracts/dummy_2.teal" +DEBUG: tealer: json output is written to {current_working_directory}/dummy_2.teal +DEBUG: Running 'tealer --json {current_working_directory}/dummy_3.teal detect --contracts {current_working_directory}/dummy_contracts/dummy_3.teal' in '{current_working_directory}' +DEBUG: tealer: Reading contract from file: "{current_working_directory}/dummy_contracts/dummy_3.teal" +DEBUG: tealer: json output is written to {current_working_directory}/dummy_3.teal +DEBUG: Running 'tealer --json {current_working_directory}/dummy_4.teal detect --contracts {current_working_directory}/dummy_contracts/dummy_4.teal' in '{current_working_directory}' +DEBUG: tealer: Reading contract from file: "{current_working_directory}/dummy_contracts/dummy_4.teal" +DEBUG: tealer: json output is written to {current_working_directory}/dummy_4.teal File: dummy_0.teal diff --git a/tests/tasks/test_analyze.test_analyze_multiple_files_recursive.approved.txt b/tests/tasks/test_analyze.test_analyze_multiple_files_recursive.approved.txt index 734046e4..d5ecb17e 100644 --- a/tests/tasks/test_analyze.test_analyze_multiple_files_recursive.approved.txt +++ b/tests/tasks/test_analyze.test_analyze_multiple_files_recursive.approved.txt @@ -1,21 +1,21 @@ DEBUG: Running 'tealer --version' in '{current_working_directory}' DEBUG: tealer: 0.1.2 Warning: This task uses `tealer` to suggest improvements for your TEAL programs, but remember to always test your smart contracts code, follow modern software engineering practices and use the guidelines for smart contract development. This should not be used as a substitute for an actual audit. Do you understand? [Y/n]: y -Running 'tealer --json {current_working_directory}/dummy_contracts/subfolder_0/dummy.teal detect --contracts {current_working_directory}/dummy_contracts/subfolder_0/dummy.teal' in '{current_working_directory}' -tealer: Reading contract from file: "{current_working_directory}/dummy_contracts/subfolder_0/dummy.teal" -tealer: json output is written to {current_working_directory}/dummy_contracts/subfolder_0/dummy.teal -Running 'tealer --json {current_working_directory}/dummy_contracts/subfolder_1/dummy.teal detect --contracts {current_working_directory}/dummy_contracts/subfolder_1/dummy.teal' in '{current_working_directory}' -tealer: Reading contract from file: "{current_working_directory}/dummy_contracts/subfolder_1/dummy.teal" -tealer: json output is written to {current_working_directory}/dummy_contracts/subfolder_1/dummy.teal -Running 'tealer --json {current_working_directory}/dummy_contracts/subfolder_2/dummy.teal detect --contracts {current_working_directory}/dummy_contracts/subfolder_2/dummy.teal' in '{current_working_directory}' -tealer: Reading contract from file: "{current_working_directory}/dummy_contracts/subfolder_2/dummy.teal" -tealer: json output is written to {current_working_directory}/dummy_contracts/subfolder_2/dummy.teal -Running 'tealer --json {current_working_directory}/dummy_contracts/subfolder_3/dummy.teal detect --contracts {current_working_directory}/dummy_contracts/subfolder_3/dummy.teal' in '{current_working_directory}' -tealer: Reading contract from file: "{current_working_directory}/dummy_contracts/subfolder_3/dummy.teal" -tealer: json output is written to {current_working_directory}/dummy_contracts/subfolder_3/dummy.teal -Running 'tealer --json {current_working_directory}/dummy_contracts/subfolder_4/dummy.teal detect --contracts {current_working_directory}/dummy_contracts/subfolder_4/dummy.teal' in '{current_working_directory}' -tealer: Reading contract from file: "{current_working_directory}/dummy_contracts/subfolder_4/dummy.teal" -tealer: json output is written to {current_working_directory}/dummy_contracts/subfolder_4/dummy.teal +DEBUG: Running 'tealer --json {current_working_directory}/dummy_contracts/subfolder_0/dummy.teal detect --contracts {current_working_directory}/dummy_contracts/subfolder_0/dummy.teal' in '{current_working_directory}' +DEBUG: tealer: Reading contract from file: "{current_working_directory}/dummy_contracts/subfolder_0/dummy.teal" +DEBUG: tealer: json output is written to {current_working_directory}/dummy_contracts/subfolder_0/dummy.teal +DEBUG: Running 'tealer --json {current_working_directory}/dummy_contracts/subfolder_1/dummy.teal detect --contracts {current_working_directory}/dummy_contracts/subfolder_1/dummy.teal' in '{current_working_directory}' +DEBUG: tealer: Reading contract from file: "{current_working_directory}/dummy_contracts/subfolder_1/dummy.teal" +DEBUG: tealer: json output is written to {current_working_directory}/dummy_contracts/subfolder_1/dummy.teal +DEBUG: Running 'tealer --json {current_working_directory}/dummy_contracts/subfolder_2/dummy.teal detect --contracts {current_working_directory}/dummy_contracts/subfolder_2/dummy.teal' in '{current_working_directory}' +DEBUG: tealer: Reading contract from file: "{current_working_directory}/dummy_contracts/subfolder_2/dummy.teal" +DEBUG: tealer: json output is written to {current_working_directory}/dummy_contracts/subfolder_2/dummy.teal +DEBUG: Running 'tealer --json {current_working_directory}/dummy_contracts/subfolder_3/dummy.teal detect --contracts {current_working_directory}/dummy_contracts/subfolder_3/dummy.teal' in '{current_working_directory}' +DEBUG: tealer: Reading contract from file: "{current_working_directory}/dummy_contracts/subfolder_3/dummy.teal" +DEBUG: tealer: json output is written to {current_working_directory}/dummy_contracts/subfolder_3/dummy.teal +DEBUG: Running 'tealer --json {current_working_directory}/dummy_contracts/subfolder_4/dummy.teal detect --contracts {current_working_directory}/dummy_contracts/subfolder_4/dummy.teal' in '{current_working_directory}' +DEBUG: tealer: Reading contract from file: "{current_working_directory}/dummy_contracts/subfolder_4/dummy.teal" +DEBUG: tealer: json output is written to {current_working_directory}/dummy_contracts/subfolder_4/dummy.teal File: 4_dummy.teal diff --git a/tests/tasks/test_analyze.test_analyze_single_file.approved.txt b/tests/tasks/test_analyze.test_analyze_single_file.approved.txt index 7210aeda..dade4314 100644 --- a/tests/tasks/test_analyze.test_analyze_single_file.approved.txt +++ b/tests/tasks/test_analyze.test_analyze_single_file.approved.txt @@ -1,9 +1,9 @@ DEBUG: Running 'tealer --version' in '{current_working_directory}' DEBUG: tealer: 0.1.2 Warning: This task uses `tealer` to suggest improvements for your TEAL programs, but remember to always test your smart contracts code, follow modern software engineering practices and use the guidelines for smart contract development. This should not be used as a substitute for an actual audit. Do you understand? [Y/n]: y -Running 'tealer --json {current_working_directory}/dummy_report.json detect --contracts {current_working_directory}/dummy.teal' in '{current_working_directory}' -tealer: Reading contract from file: "{current_working_directory}/dummy.teal" -tealer: json output is written to {current_working_directory}/dummy_report.json +DEBUG: Running 'tealer --json {current_working_directory}/dummy_report.json detect --contracts {current_working_directory}/dummy.teal' in '{current_working_directory}' +DEBUG: tealer: Reading contract from file: "{current_working_directory}/dummy.teal" +DEBUG: tealer: json output is written to {current_working_directory}/dummy_report.json File: dummy_report.json diff --git a/tests/tasks/test_analyze.test_exclude_vulnerabilities.approved.txt b/tests/tasks/test_analyze.test_exclude_vulnerabilities.approved.txt index 483ea466..fcf587be 100644 --- a/tests/tasks/test_analyze.test_exclude_vulnerabilities.approved.txt +++ b/tests/tasks/test_analyze.test_exclude_vulnerabilities.approved.txt @@ -1,6 +1,6 @@ DEBUG: Running 'tealer --version' in '{current_working_directory}' DEBUG: tealer: 0.1.2 Warning: This task uses `tealer` to suggest improvements for your TEAL programs, but remember to always test your smart contracts code, follow modern software engineering practices and use the guidelines for smart contract development. This should not be used as a substitute for an actual audit. Do you understand? [Y/n]: y -Running 'tealer --json {current_working_directory}/dummy_report.json detect --contracts {current_working_directory}/dummy.teal --exclude is-deletable, missing-fee-check, rekey-to' in '{current_working_directory}' -tealer: Reading contract from file: "{current_working_directory}/dummy.teal" -tealer: json output is written to {current_working_directory}/dummy_report.json +DEBUG: Running 'tealer --json {current_working_directory}/dummy_report.json detect --contracts {current_working_directory}/dummy.teal --exclude is-deletable, missing-fee-check, rekey-to' in '{current_working_directory}' +DEBUG: tealer: Reading contract from file: "{current_working_directory}/dummy.teal" +DEBUG: tealer: json output is written to {current_working_directory}/dummy_report.json diff --git a/tests/version_check/test_version_check.py b/tests/version_check/test_version_check.py index 51737d16..7af079fd 100644 --- a/tests/version_check/test_version_check.py +++ b/tests/version_check/test_version_check.py @@ -4,7 +4,7 @@ import pytest from algokit.core.conf import PACKAGE_NAME -from algokit.core.version_prompt import LATEST_URL, VERSION_CHECK_INTERVAL +from algokit.core.config_commands.version_prompt import LATEST_URL, VERSION_CHECK_INTERVAL from approvaltests.scrubbers.scrubbers import Scrubber, combine_scrubbers from pytest_httpx import HTTPXMock from pytest_mock import MockerFixture @@ -28,8 +28,12 @@ def make_scrubber(app_dir_mock: AppDirs) -> Scrubber: @pytest.fixture(autouse=True) def _setup(mocker: MockerFixture, app_dir_mock: AppDirs) -> None: - mocker.patch("algokit.core.version_prompt.get_app_config_dir").return_value = app_dir_mock.app_config_dir - mocker.patch("algokit.core.version_prompt.get_app_state_dir").return_value = app_dir_mock.app_state_dir + mocker.patch( + "algokit.core.config_commands.version_prompt.get_app_config_dir" + ).return_value = app_dir_mock.app_config_dir + mocker.patch( + "algokit.core.config_commands.version_prompt.get_app_state_dir" + ).return_value = app_dir_mock.app_state_dir # make bootstrap env a no-op mocker.patch("algokit.cli.project.bootstrap.bootstrap_env") @@ -75,7 +79,9 @@ def test_version_check_queries_github_when_no_cache(app_dir_mock: AppDirs, httpx def test_version_check_only_warns_if_newer_version_is_found( app_dir_mock: AppDirs, mocker: MockerFixture, current_version: str, latest_version: str, *, warning_expected: bool ) -> None: - mocker.patch("algokit.core.version_prompt.get_current_package_version").return_value = current_version + mocker.patch( + "algokit.core.config_commands.version_prompt.get_current_package_version" + ).return_value = current_version version_cache = app_dir_mock.app_state_dir / "last-version-check" version_cache.write_text(latest_version, encoding="utf-8") result = invoke("project bootstrap env", skip_version_check=False) @@ -154,9 +160,9 @@ def test_version_check_enable_version_check(app_dir_mock: AppDirs) -> None: def test_version_prompt_according_to_distribution_method( mocker: MockerFixture, app_dir_mock: AppDirs, method: str, message: str ) -> None: - mocker.patch("algokit.core.version_prompt._get_distribution_method").return_value = method - mocker.patch("algokit.core.version_prompt.is_binary_mode").return_value = True - mocker.patch("algokit.core.version_prompt.get_current_package_version").return_value = "1.0.0" + mocker.patch("algokit.core.config_commands.version_prompt._get_distribution_method").return_value = method + mocker.patch("algokit.core.config_commands.version_prompt.is_binary_mode").return_value = True + mocker.patch("algokit.core.config_commands.version_prompt.get_current_package_version").return_value = "1.0.0" version_cache = app_dir_mock.app_state_dir / "last-version-check" version_cache.write_text("2.0.0", encoding="utf-8")