Coder Social home page Coder Social logo

javajon / katacoda-solver Goto Github PK

View Code? Open in Web Editor NEW
2.0 2.0 2.0 10.17 MB

Solver is a command-line interface (CLI) that helps authors create O'Reilly Challenges. The Solver utility helps authors organize the verifications, the myriad of hints, and provides an enhanced solutions mechanism for rapid testing. Solver is not required, but it can shorten your time for producing quality Challenges.

Home Page: https://katacoda.com/scenario-examples/courses/challenges

License: MIT License

Kotlin 2.06% Java 93.92% Shell 4.02%
o-reilly cli challenges java picocli gradle graal quarkus

katacoda-solver's Introduction

Solver Tool for Authoring O'Reilly Challenges

Solver is a command-line interface (CLI) that helps authors create O'Reilly Challenges. Solver helps authors organize the verifications, the myriad of hints, and provides an enhanced solutions mechanism for rapid testing. Solver is not required, but it can shorten your time for producing quality Challenges.

The usage of Solver for O'Reilly Challenge authors is detailed in the Katacoda Documentation.

The command line offers information on the commands via solver --help.

If you are an author using this utility, your feedback is important, and please feel free to add issues in this project for reporting problems or suggesting ideas.

Running Solver for Authors

As an author there are two places where Solver can help you:

  1. Locally in your development environment when creating the content
  2. At runtime, within the challenge.

Solver is a tool that both supports your challenge development and execution.

These two installations types are covered in the documentation at Challenges Solver Utility.

Solver on Windows and MacOS

The solver CLI utility binary is targeted for Linux. To use Solver while you are developing your challenge on Windows or macOS one option is to run the utility from the published container for solver. Here is a bash function that you can apply if you decide to use a bash terminal on Windows or macOS:

function solver() {
  SOLVER_IMAGE=ghcr.io/javajon/solver:0.5.4   ## <-- Set to the latest semver release @ https://bit.ly/3sSEiBD
  SCENARIOS_ROOT=~/my-scenarios               ## <-- Set to your base source directory for your challenges and scenarios
  if [[ ! "$(pwd)" =~ ^$SCENARIOS_ROOT.* ]]; then
    echo "Please run this from $SCENARIOS_ROOT or one of its scenario or challenge subdirectory."
    return 1;
  fi
  SUBDIR=$(echo $(pwd) | grep -oP "^$SCENARIOS_ROOT\K.*")    ## <-- change to ggrep if on macOS
  docker run --rm -it -v "$SCENARIOS_ROOT":/workdir -w /workdir/$SUBDIR $SOLVER_IMAGE "$@";
}

macOS Nuance

The above function expects GNU grep. This is not the version installed by default on macOS. You can easily install the GNU version by using homebrew and then just changing the call to grep in the above function to ggrep.

Windows Nuance

On Windows, another option is wsl2.


The remaining instructions are for developers of this utility, not for authors of the challenges.

Architecture stack

This command-line tool is written in Java. Picocli is leveraged for the CLI framework. Quarkus with Graal creates a fast and efficient Linux binary. The project is built with Gradle and CI/CD is automated using GitHub actions.

Running App in Dev Mode

You can run your application in developer mode that enables live coding using:

./gradlew quarkusDev

Packaging and Running

The application can be packaged using:

./gradlew build

It produces the quarkus-run.jar file in the build/quarkus-app/ directory. Be aware that it’s not an über-jar as the dependencies are copied into the build/quarkus-app/lib/ directory.

If you want to build an über-jar, execute the following command:

./gradlew build -Dquarkus.package.type=uber-jar

The application is now runnable using java -jar build/quarkus-app/quarkus-run.jar.

Creating Native Executable

You can create a native executable using:

./gradlew build -Dquarkus.package.type=native -Dquarkus.native.native-image-xmx=8g

Or, if you don't have GraalVM installed, you can run the native executable build in a container using:

./gradlew build -Dquarkus.package.type=native -Dquarkus.native.container-build=true -Dquarkus.native.native-image-xmx=8g

If the quarkusBuild fails with an exit code 137 out of memory message, the error message suggests increasing the xmx heap size. Others indicate this is a problem with your local docker engine. Consider a purge of your docker engine caches docker purge system --all followed with a full host reboot.

With either of the above, you can then execute your native executable with:

./build/solver-[version]-runner

This binary, renamed to solver, may be used by a Challenge.

Developing and Debugging the Solver project code

If you are a developer or tester of the Solver utility below are some techniques to run it locally or copy it to a Challenge without the GitOps process.

You can run solver from Linux shells, but without the context of an O'Reilly Challenge, it is like watching Fred Flintstone drive a car with his feet with no engine. You're not fooling anyone, Fred.

Run Locally via über-jar

./gradlew build -Dquarkus.package.type=uber-jar && java -jar build/quarkus-app/quarkus-run.jar --help

Installing Solver into a Challenge

The solver command-line tool cannot be loaded via the scenario's assets as there is a size limit at 9MB and the CLI tool is too large of an asset. Instead, there is a wget command in the init-background.sh script that installs Solver when the challenge starts. This incurs a slight vulnerability if GitHub fails to deliver the requested CLI binary artifact from the release page then the challenge will break and the learner will have to reload the scenario. This source may change and remains on the roadmap.

Ensure the wget pulls a specific version of Solver and your challenge is tested with that specific version in place.

Rapid Development Testing

For fast, local, iterative development and testing of the Solver tool with a live challenge it's best to copy the updated Solver binary directly to the challenge. There are a variety of places where a binary can be uploaded. Here is an example using the public service transfer.sh

  1. Build the binary with
    ./gradlew build -Dquarkus.package.type=native -Dquarkus.native.container-build=true
  2. Identify the binary to copy:
    export SOLVER_RUNNER=build/solver-$(git describe --tags $(git rev-list --tags --max-count=1))-$(git rev-parse --abbrev-ref HEAD)-runner
    
  3. Upload the executable to an ephemeral cloud directory:
    STORAGE_URL=$(curl --upload-file $SOLVER_RUNNER https://transfer.sh/solver) && echo $STORAGE_URL
  4. Copy the resulting storage URL to your clipboard.
  5. Start Challenge
  6. Copy solver binary into Challenge using the clipboard pasted URL:
    curl -o solver <pasted-url>
  7. Make executable, copy, and verify:
    chmod +x solver && cp solver /usr/local/bin && solver --version

Some of these public services throttle throughput over repeated usage. You can also use gdrive to download artifacts from Google drive. Never use these for the published challenges.

To compress the binary before transfer use UPX. The releases are compressed with this UPX tool:

  • Install UPX with
    sudo apt-get update && yes | sudo apt-get install upx
    
  • Compress the executable with:
    upx --best --lzma $solver
    

Solver Version Tracking

Solver uses SemVer and the versions are tracked and bumped automatically. A release is created for any commit with a new SemVer git tag. There are GitHub actions to build, tag, and create releases. The SemVer tagging, bumping, and releasing process is based on the GitHub action jefflinse/pr-semver-bump.

Direct commits are not permitted to the main branch via a GitHub branch rule. Only PRs are committed to main. A Merged pull request (PR) triggers the automated SemVer advancement and a new release. With this comes the PR comments and PR labels and direct the bumping of the major, minor, and patch numbers. When a PR is merged to main, it must be labeled with either major, minor, or patch. When a new SemVer tag is created a new GitHub release is created with the update solver binary. This technique follows some best practices for automated GitOps. Branch names can be reused, such as update. The workflow for the PR roughly follows this flow:

git checkout -b update
(make changes)
git add .
git commit -m "(the reasons for the new release)"
git push --set-upstream origin update

In GitHub merge the pull request and be sure to add the label patch release, as described here.

Related Guides

Origins

This project was inspired by the try-picocli-gradle repository.

katacoda-solver's People

Contributors

javajon avatar spkane avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

Forkers

spkane kubz

katacoda-solver's Issues

Implement "solver lint"

At least for authoring mode the "solver lint" command should check for problems.

Added to upcoming release.

Bug: In testing a challenge, run decrypt command BEFORE running solver view, next, all, and until

There is a mild bug in solver which will be fixed in the next revision.

However, in the meantime just be sure to run the decrypt command BEFORE running solver view, next, all, and until. Running some commands before the decrypt creates a bogus file. If you happen to run a command before the decrypt command or encounter this problem again just delete the file:

rm /tmp/solutions-sourcer.sh

The command "solver view 1" was also producing the message: "Solutions not found for requested task 1"

You can clear out the bug with:

rm /tmp/solutions-sourcer.sh
solver sol -d K0MS1DPSEK833Q13
solver view 1

And you will see the solution appear as expected. At this point solver next, all, and until will work..

The simple thing to remember is just do the decrypt command first just after the scenario starts.

CI/CD improvements

  • Move most CI work to stages in dockerfile and have actions pull binary from the container to publish on the release page.
  • Move gradlew build to inside dockerfile stage rather than at GitHub action level
  • Simplify the readme for build instructions
  • Remove UPX as a GitHub action step and substitute with Quarkus UPX switch.
  • Consider other high availability options for CLI tool download

Allow the working directory to be configured for all commands

First thing Jonathan, great work on this tool. It looks like it will be very helpful!

I am running into an issue using it in my environment, however.

I am trying to use solver on a Mac while I am developing a challenge and I have run into a few issues when running it inside a container.

The Katacoda documents here: https://www.katacoda.community/challenges/challenges-solver.html

recommend that you use it by setting alias solver="docker run --rm ghcr.io/javajon/solver:0.4.1

However, running a command like this would fail solver create --archetype=linux --destination=. --force

I figured that this was because it was running inside the container, so I removed the alias and replaced it with a bash function that looks like this:

solver ()
{
    docker run --rm -v `pwd`:/output ghcr.io/javajon/solver:0.4.1 "$@"
}

This then allowed me to run solver create --archetype=linux --destination=/output --force without an issue.

However, when I got done with the challenge and then wanted to encrypt the solutions, I ran into another problem. I see no way to tell solver where to find the solutions, which means that I can't point it at the mounted directory.

Running solver solutions -e, claims to have done something (which surprises me a bit), but once again this is likely happening inside the container filesystem.

It seems like the tool really needs an option to specific the working directory, for most, if not all commands. This should allow users on Windows and Mac to use it reasonably easily, and would definitely help me out.

Let me know if there is anymore information or testing that I can do, which would be helpful!

Some shell commands in verifications.sh can fail silently

When a command like curl fails silently in validations.sh the command solver verify can in some cases report true, yet the framework still fails to advance to the next task. More can be done to trap and detect these quiet failures.

For each hint allow hint reveal delay based on seconds

There is currently a fixed 3-second delay on each hint. (in SubcommandRequestHint.java, taskUptime > 3). Typically the 3 seconds is shorter than when the learner reveals the hint. In the next version, it with be an optional adjustment by the author, set to a short default, perhaps 0,1, or 2 based on testing. A slight delay of ~1 second rather than 0, may still be wanted more for performance reasons.

  1. Overall there will be a global delay setting defaulted to 0, this global default setting may be adjusted by the author.
  2. In the markdown for each hint, there will be an optional time delay.

Units are in seconds.

Overall time delays are not encouraged as time is very subjective based on each learner's speed, distractions, hardware, skills, and accessibility.

These details will be added to the challenge documentation.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.