Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: GitHub Codespaces support in LocalNet command group #456

Merged
merged 33 commits into from
Jun 11, 2024

Conversation

aorumbayev
Copy link
Collaborator

@aorumbayev aorumbayev commented Mar 19, 2024

Spike following the https://github.com/orgs/algorandfoundation/projects/1/views/1?filterQuery=aorum&pane=issue&itemId=56476748

Proposed Changes

This document serves as an informal Architecture Decision Record (ADR). Proceedings from the PR discussion will be converted to an ADR markdown file later.

Motivation

A significant number of users attending bootcamps encountered scenarios where their devices had hardware incompatibilities with Docker (primarily certain Windows 10 variations). The proposal aims to provide a convenient built-in experience that leverages GitHub CLI capabilities to provision a dummy Codespace instance (using the Algokit base template as a target) to port forward localnet ports to the user's machine.

Proposal

The idea is to provide a new command under localnet group to cover this scenario for users experiencing issues with docker. We can rely on GitHub CLI to leverage codespaces and their port-forwarding capabilities, allowing the Algokit CLI to lazily load the dependency if not present. The current proof of concept assumes winget for Windows and uses a 'webi' executable on Unix devices.

On the first login, the user is redirected to GitHub CLI's interactive authentication flow. Afterward, any existing Codespaces with the 'sandbox' prefix are automatically deleted. Finally, a fresh Codespace is created, and after a 60-second sleep (a holistic estimate for base machine quota, roughly half for container boot, and the remaining quarters for pipx algokit install and starting the localnet), the indexer, algod, and kmd ports from the Codespace are redirected to the user's machine. The user can then open a new tab and interact with the localnet as if it were running locally (similar to the Docker-based experience).

Pros

  • One of the simplest ways to solve the main requirement of providing alternative mechanisms for users to access localnet if Docker is not an option. It's important to maintain the Docker-based approach as the recommended option, given that Docker still offers advantages in offline local development scenarios and abstract away heaps of 'native' complexity. However, a simple, interactive experience within the localnet command group that provides a free quota-based temporary on-demand instance can offer a flexible alternative solution for any edge case where Docker is unavailable for local development.
  • Embraces the notion of dev containers, which are actively propagated by official Algokit templates. Provides a marginally similar experience to using the Docker-based localnet.
  • GitHub CLI is available on a massive array of architectures and operating systems, both as native binaries and via major package managers, allowing conditional handling of main variations by picking the appropriate distribution channel to obtain the artifact.

Cons and Minor Notes

  • Cannot work offline.
  • Similar to the Docker-based approach, for simplicity, we assume that only one Codespace-based localnet instance can be up and running (otherwise, default ports will clash). An advanced developer can always tailor the ports as needed, so it's more of an inconvenience for beginners.

Next steps

  • - address comments, gather feedback on the proposal. Which parts of the initial poc can be further refined/improved?
  • - if this proposal or a modified version based on final discussion in the pr are accepted, the pr implementation is to be refined, covered with snapshot tests and documented.

How to play around with the poc ?
pipx install git+https://github.com/algorandfoundation/algokit-cli@feat/codespaces-localnet --force then algokit localnet codespace start

Copy link

github-actions bot commented Mar 19, 2024

Coverage

Coverage Report
FileStmtsMissCoverMissing
src/algokit
   __init__.py15753%6–13, 17–24, 32–34
   __main__.py440%1–7
src/algokit/cli
   __init__.py47394%31–34
   codespace.py50982%28, 114, 137, 150–155
   completions.py108992%63–64, 83, 93–99
   dispenser.py121199%77
   doctor.py53394%146–148
   explore.py501276%34–39, 41–46
   generate.py70396%76–77, 155
   goal.py47198%79
   init.py3092492%493–494, 499–500, 503, 524, 527–529, 540, 544, 602, 628, 657, 690, 699–701, 704–709, 722, 741, 753–754
   localnet.py1523279%65, 86–113, 133–137, 170, 182, 197–207, 220, 271, 292–293
   task.py34391%25–28
src/algokit/cli/common
   utils.py26292%120, 123
src/algokit/cli/project
   bootstrap.py32197%33
   deploy.py992080%47, 49, 101, 124, 146–148, 227, 234, 248–256, 259–268
   link.py891682%60, 65–66, 101–105, 115–120, 148–149, 218–219, 223
   list.py33585%21–23, 51–56
   run.py46393%38, 71, 160
src/algokit/cli/tasks
   analyze.py81199%81
   assets.py821384%65–66, 72, 74–75, 105, 119, 125–126, 132, 134, 136–137
   ipfs.py51884%52, 80, 92, 94–95, 105–107
   mint.py66494%48, 70, 91, 250
   send_transaction.py651085%52–53, 57, 89, 158, 170–174
   sign_transaction.py59886%21, 28–30, 71–72, 109, 123
   transfer.py39392%26, 90, 117
   utils.py994555%26–34, 40–43, 75–76, 100–101, 125–133, 152–162, 209, 258–259, 279–290, 297–299
   vanity_address.py561082%41, 45–48, 112, 114, 121–123
   wallet.py79495%21, 66, 136, 162
src/algokit/core
   codespace.py1756861%34–37, 41–44, 48–71, 111–112, 125–133, 191, 200–202, 210, 216–217, 229–236, 251–298, 311–313, 338–344, 348, 395
   conf.py57984%12, 24, 28, 36, 38, 73–75, 80
   dispenser.py2022687%91, 123–124, 141–149, 191–192, 198–200, 218–219, 259–260, 318, 332–334, 345–346, 356, 369, 384
   doctor.py65789%67–69, 92–94, 134
   generate.py48394%44, 81, 99
   goal.py65494%21, 36–37, 47
   init.py671085%53, 57–62, 70, 81, 88, 108–109
   log_handlers.py68790%50–51, 63, 112–116, 125
   proc.py45198%99
   sandbox.py2532391%32, 84–87, 92, 96–98, 145, 192–199, 210, 502, 518, 543, 551
   typed_client_generation.py1702088%62–64, 103–108, 132, 135–138, 156, 159–162, 229, 232–235
   utils.py1463874%50–51, 57–66, 122–128, 152, 155, 161–174, 195–197, 226–229, 251
src/algokit/core/compilers
   python.py28582%19–20, 25, 49–50
src/algokit/core/config_commands
   container_engine.py412149%24, 29–31, 47–76
   version_prompt.py921485%37–38, 68, 87–90, 108, 118–125, 148
src/algokit/core/project
   __init__.py53394%50, 86, 145
   bootstrap.py120893%47, 126–127, 149, 176, 207–209
   deploy.py54983%61–64, 73–75, 79, 84
   run.py1251588%83, 88, 97–98, 133–134, 138–139, 143, 147, 261–269, 284
src/algokit/core/tasks
   analyze.py93397%105–112, 187
   ipfs.py63789%58–64, 140, 144, 146, 152
   nfd.py491373%25, 31, 34–41, 70–72, 99–101
   vanity_address.py903462%49–50, 54, 59–75, 92–108, 128–131
   wallet.py71593%37, 129, 155–157
src/algokit/core/tasks/mint
   mint.py781087%123–133, 187
   models.py901188%50, 52, 57, 71–74, 85–88
TOTAL462263886% 

Tests Skipped Failures Errors Time
487 0 💤 0 ❌ 0 🔥 24.500s ⏱️

@aorumbayev aorumbayev changed the title [draft] feat - mvp proposal for integration localnet with codespaces [draft] feat - mvp proposal for integrating gh codespaces into 'localnet' Mar 19, 2024
@ShoGinn
Copy link

ShoGinn commented Mar 23, 2024

@aorumbayev This is an epic feature; I've been trying to implement an offline container-agnostic approach since, as you stated, using Docker can be problematic.

My approach is similar to yours in that we need a local network engine. Thank you for not destroying the local network design. I'm adding this to my workboard, but this might be a better stopgap.

@ShoGinn
Copy link

ShoGinn commented Mar 23, 2024

@aorumbayev I could not get the pull to work without docker installed... I'm guessing its in the localnet group of the cli erroring out.

@neilcampbell
Copy link
Contributor

neilcampbell commented Mar 23, 2024

@ShoGinn Nice find, you're spot on. The presence of docker is checked when the localnet command group is loaded. At the moment this PR is a quick spike to see what is possible, so a bit rough around the edges.

@aorumbayev aorumbayev mentioned this pull request Mar 25, 2024
6 tasks
@aorumbayev aorumbayev force-pushed the feat/codespaces-localnet branch from 3692d77 to e5c7a4f Compare March 26, 2024 11:05
@aorumbayev
Copy link
Collaborator Author

@ShoGinn this is still a preview mvp, but i patched the issue you had with docker, feel free to retry again

@ShoGinn
Copy link

ShoGinn commented Mar 26, 2024

@ShoGinn this is still a preview mvp, but i patched the issue you had with docker, feel free to retry again

I actually tried it when I saw you made some commits. It works great, and I'm excited to see how it progresses.

This solution is much cleaner than local docker/podman and enables a solid dev environment.

I think the CLI is going to be the biggest work. My recommendation is that rather than having dappflow or other commands check for the engine, have it check for the URL: port, but that's just a recommendation.

@aorumbayev aorumbayev force-pushed the feat/codespaces-localnet branch 2 times, most recently from 47396d1 to d94d8c6 Compare April 3, 2024 13:33
@aorumbayev
Copy link
Collaborator Author

@neilcampbell @robdmoore @Loedn , ill still keep pr description as adr up until this pr is closed/merged/resolved.
For now assume this comment is the description (since initially it was a draft mvp, latest commits polish up the experience and add docs and tests)

Proposed changes

  • algokit localnet codespace command - a single command that takes care of one full lifecycle from creation to termination -(user can opt out from auto cleanup with force flag) of a github codespace where upon localnet being booted inside the container - algokit cli will rely on gh cli to port forward the kmd algod and indexer to local network. See docs for detailed breakdown of behaviour and/or pipx install the branch to try it out yourself
  • minor refinements, improving the start_with_animation spinner to gracefully handle keyboard interrupts.
  • initial batch of snap shot tests (TODO: more to be added tomorrow)
  • initial documentation

(cc @ShoGinn , feel free to check it out comment too, first hand user feedback is always welcome! :-) )

@aorumbayev aorumbayev marked this pull request as ready for review April 3, 2024 16:04
@aorumbayev aorumbayev changed the title [draft] feat - mvp proposal for integrating gh codespaces into 'localnet' feat: GitHub Codespaces support in LocalNet command group Apr 3, 2024
@ShoGinn
Copy link

ShoGinn commented Apr 5, 2024

@aorumbayev I did some tests with the latest code; the codespace will start without start (I'm not sure if that is intended). algokit localnet codespace I expected the cli to provide some instruction without start.

Also, because the cli is always looking for docker, it won't work for algokit localnet explore etc

I would recommend that localnet include codespace or docker for commands, dig deeper for things like logs, etc., and make the explore and console less restrictive, just naturally failing or checking ports rather than files.

@aorumbayev
Copy link
Collaborator Author

aorumbayev commented Apr 5, 2024

@ShoGinn hey thank you for checking it out!

RE: starting without start
This is indeed intended behaviour, that was changed in this commit. The reasoning was due to the fact that the command is mainly designed to work with on-demand codespaces that it creates (unless a -n name to a specific instance is provided in such cases it will try to just reconnect to an existing instance). There were no direct use cases for stop, reset and reset --update and having them integrated under docker based localnet command groups can put a lot more coupling with gh cli and we still want to maintain a fairly light set of features that cli wraps for the user (because gh cli by itself is very flexible and user friendly out of the box). The initial draft you tried was still an early mvp, so starting from last 2-3 commits you can expect a lot less breaking changes until this pr is finalized. One way to look at the new behaviour (dropping explicit codespace start) is similar to how kubectl behaves when it comes to port forwarding.

RE: explore
Good point! I will make sure it can work with both codespace and docker based modes. (will let you know once commit is in place)

RE: 'I would recommend that localnet include codespace or docker for commands'
I got the second half of this but regarding this specific bit, can you expand a little bit more? What are you referring to when you are mentioning localnet? A command group within cli or the group of containers representing the localnet ?

For extra reference while this pr is open you can access the new docs covering this command from here https://github.com/algorandfoundation/algokit-cli/blob/feat/codespaces-localnet/docs/features/localnet.md#github-codespaces-based-localnet

@ShoGinn
Copy link

ShoGinn commented Apr 5, 2024

@ShoGinn hey thank you for checking it out!

RE: starting without start This is indeed intended behaviour changes in this commit. The reasoning was due to the fact that the command is mainly designed to work with on-demand codespaces that it creates (unless a -n name to a specific instance is provided in such cases it will try to just reconnect to an existing instance). There were no use cases for stop, reset and reset --update and having them integrated under docker based localnet command groups can put a lot more coupling with gh cli and we still want to maintain a fairly light set of features that cli wraps for the user (because gh cli by itself is very flexible and user friendly out of the box). The initial draft you tried was still an early mvp, so i'd say you can expect a lot less breaking changes until this pr is finalized.

Makes sense!

RE: explore Good point! I will make sure it can work with both codespace and docker based modes. (will let you know once commit is in place)

Can't wait!

RE: 'I would recommend that localnet include codespace or docker for commands' I got the second half of this but regarding this specific bit, can you expand a little bit more? What are you referring to when you are mentioning localnet? A command group within cli or the group of containers representing the localnet ?

Sorry this was a fragmented thought! I just meant in the cli make commands specific to the docker portion a sub-command in the cli.

  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.

All of these commands should be under algokit localnet docker

that way when implemented you know what features are what.

algokit localnet
Usage: algokit localnet [OPTIONS] COMMAND [ARGS]...

Options:
  -h, --help  Show this message and exit.

Commands:
  codespace  Manage the AlgoKit LocalNet in GitHub Codespaces.
  docker     Manage the Algokit LocalNet in local Docker environment
  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

@aorumbayev
Copy link
Collaborator Author

@ShoGinn i see, i do agree that it does make the command group semantics a bit cleaner (given that this pr is now introducing an alternative mechanism to accessing the localnet).

  1. Your option -> one way this could be done without breaking changes is applying the same process we did to algokit bootstrap and deploy commands at the root command level in latest v2 release. They are still there yet they are hidden from help and upon invoking you see a deprecation warning. However, that would still require an eventual change in majority of algokit repos to switch to new syntax (and any algokit based project relying on it). This is a bit of a broader suggestion, i wonder what are your opinions on this @robdmoore @Loedn @neilcampbell ?)

  2. Alternative, moving the codespace under task command group. While having codespaces under localnet makes sense (and codespaces approach being part of a solution to a formal outcome related to localnet), we also have a separate command group category called tasks which we use exclusively for extra utils OR integrations with external tools (see algokit task analyze for instance). As an alternative we can also move this codespace command under algokit task command group. That wouldn't require a breaking change in a large majority of existing algokit repos and projects used to invoking localnet directly without extra docker command group. Curious on opinions for this option as well.

@neilcampbell
Copy link
Contributor

Your option -> one way this could be done without breaking changes is applying the same process we did to algokit bootstrap and deploy commands at the root command level in latest v2 release. They are still there yet they are hidden from help and upon invoking you see a deprecation warning. However, that would still require an eventual change in majority of algokit repos to switch to new syntax (and any algokit based project relying on it). This is a bit of a broader suggestion, i wonder what are your opinions on this @robdmoore @Loedn @neilcampbell ?)

It's definitely an option. I do quite like that we are somewhat decoupled from Docker with the command semantics, as I guess it's still possible LocalNet could be an entirely native setup.

Alternative, moving the codespace under task command group. While having codespaces under localnet makes sense (and codespaces approach being part of a solution to a formal outcome related to localnet), we also have a separate command group category called tasks which we use exclusively for extra utils OR integrations with external tools (see algokit task analyze for instance). As an alternative we can also move this codespace command under algokit task command group. That wouldn't require a breaking change in a large majority of existing algokit repos and projects used to invoking localnet directly without extra docker command group. Curious on opinions for this option as well.

A potential issue with this approach is discoverability. It's probably not the first place someone will look to run a hosted LocalNet. What would the command be in this case algokit task codespace localnet? It does allow for the extensibility of adding other potential codespace features in the future.

I think there are pros and cons of the approaches. Let's chat to work them out and make a decision.

docs/features/localnet.md Outdated Show resolved Hide resolved
docs/features/localnet.md Outdated Show resolved Hide resolved
docs/features/localnet.md Outdated Show resolved Hide resolved
docs/features/localnet.md Outdated Show resolved Hide resolved
docs/features/localnet.md Outdated Show resolved Hide resolved
@@ -120,3 +122,24 @@ 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
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should put some info to justify why we run an interactive session. This should be a nice segue into some brief content a the free and linking to the GH docs to show the current free limits.

I think it would also be good to link to the docs for setting up spending limits, to ensure users have the info needed to ensure they don't get unexpected bills. I believe by default the spending limits are $0, however I think this is still good to include. https://docs.github.com/en/billing/managing-billing-for-github-codespaces/about-billing-for-github-codespaces#setting-a-spending-limit

Copy link
Contributor

Choose a reason for hiding this comment

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

What was the outcome with regards to inactivity timeouts? Does port forwarding prevent the inactivity timeout from ever triggering.

src/algokit/core/codespace.py Outdated Show resolved Hide resolved
src/algokit/cli/codespace.py Outdated Show resolved Hide resolved
@Loedn
Copy link
Contributor

Loedn commented May 14, 2024

I would keep the localnet functionality outside of the task namespace, so that the end user can still type algokit localnet start, I would probably go down the avenue of having an algokit localnet config command where the end user decides which localnet to trigger by default with the options being: standard, custom, codespaces.
Thoughts?

@aorumbayev
Copy link
Collaborator Author

@ShoGinn sorry it took a while to get back to this since we were focused on other higher priority items.

Feel free to track the progress on this in the newly created github issue here, #504. You can assume the codespaces to be available on algokit cli as soon as that issue is closed.

@aorumbayev aorumbayev force-pushed the feat/codespaces-localnet branch from c89a980 to 9f2af80 Compare June 3, 2024 15:14
@aorumbayev aorumbayev requested a review from neilcampbell June 3, 2024 15:14
@aorumbayev
Copy link
Collaborator Author

@neilcampbell @robdmoore podman is rather tricky to install on github actions, ubuntu registry has an outdated version and running on m1 macs require a lot of extra setup that will slow down the build. Should we address the ci bit for it separately? Otherwise ready for re-review:

  1. Podman integration is in place so using algokit localnet config will allow user to use the preferred container registry
  2. Further refined the compose integration

docs/features/localnet.md Outdated Show resolved Hide resolved
docs/features/localnet.md Outdated Show resolved Hide resolved
docs/features/localnet.md Outdated Show resolved Hide resolved
src/algokit/cli/doctor.py Show resolved Hide resolved
src/algokit/cli/doctor.py Outdated Show resolved Hide resolved
@aorumbayev aorumbayev requested a review from neilcampbell June 4, 2024 23:34
on:
pull_request:
schedule:
- cron: "0 8 * * 1" # Each monday 8 AM UTC
Copy link
Collaborator Author

@aorumbayev aorumbayev Jun 5, 2024

Choose a reason for hiding this comment

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

Fyi @robdmoore @neilcampbell this for now is manually set on the repo but I mentioned to @Loedn that if there will be a github app available on foundation's org account we can use that later on to securely auth requests to trigger these checks from a single pipeline that we can place on the https://github.com/algorandfoundation/algokit repo (without the need to deal with PATs, but obv this would not be the only advantage, can simplify cross repo communication by a great extent, we can also properly use branch protection rules that way). @Loedn for the time being though this will be set as a manual cron only covering the cli repo, as soon as the bot is available for use to auth just let me know

@aorumbayev aorumbayev requested a review from neilcampbell June 6, 2024 00:15
@aorumbayev
Copy link
Collaborator Author

@neilcampbell switched to webi installer on windows too and the official installer recommends restarting the terminal session so ive matched the cli behaviour with that, if gh is not installed it will exit upon auto installation and user will need to re run the codespace command upon restart of the terminal (will update the docs on this tomorrow).
Other than that added extra idle timeout parameter, just port forwarding without doing anything extra is considered idle as well so user can set up up to 240 minutes of active state before codespace is shut down, each time there is any sort of interaction with the forwarded localnet the timer will be reset.

proc_mock.should_fail_on(
["gh", "--version"],
)
proc_mock.set_output(["powershell", "--version"], ["PowerShell 7.2.1"])
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't believe that powershell --version is available.

Copy link
Contributor

@neilcampbell neilcampbell Jun 6, 2024

Choose a reason for hiding this comment

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

I also get the following error when the webi installer runs. It still installs though. I'm running PowerShell 7.3.6.

Set-ExecutionPolicy : The 'Set-ExecutionPolicy' command was found in the module 'Microsoft.PowerShell.Security', but the module could not be loaded. For more information, run 'Import-Module

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@neilcampbell should be resolved now, powershell is checked via different command that is more versatile.

The Set-ExecutionPolicy on the other hand is a bit tricky to replicate, whats the output of Get-ExecutionPolicy -List on your side when you run it in powershell on windows (preferably same environment as the one where the error occurred during install).

Copy link
Contributor

Choose a reason for hiding this comment

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

@aorumbayev Output is this:
Scope ExecutionPolicy


MachinePolicy Undefined
UserPolicy Undefined
Process Undefined
CurrentUser Undefined
LocalMachine RemoteSigned

Copy link
Contributor

Choose a reason for hiding this comment

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

@aorumbayev Forgot to mention I was running algokit -v localnet codespace.
When running without -v it works fine without any error being printed, so we can ignore this.

@aorumbayev aorumbayev requested a review from neilcampbell June 6, 2024 16:23
src/algokit/cli/codespace.py Outdated Show resolved Hide resolved
src/algokit/cli/codespace.py Outdated Show resolved Hide resolved
src/algokit/cli/codespace.py Outdated Show resolved Hide resolved
src/algokit/core/codespace.py Outdated Show resolved Hide resolved
@aorumbayev aorumbayev merged commit 7eeaead into main Jun 11, 2024
14 checks passed
@aorumbayev aorumbayev deleted the feat/codespaces-localnet branch June 11, 2024 07:55
@aorumbayev
Copy link
Collaborator Author

@ShoGinn codespaces support is out and available under this release version https://github.com/algorandfoundation/algokit-cli/releases/tag/v2.1.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants