-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
340 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
name: Build Rustfinity Runner | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
- staging | ||
|
||
paths: | ||
- "crates/rustfinity-runner/**" | ||
- "challenges/**" | ||
|
||
jobs: | ||
publish: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v4 | ||
|
||
- name: Set up QEMU | ||
uses: docker/setup-qemu-action@v3 | ||
|
||
- name: Set up Docker Buildx | ||
uses: docker/setup-buildx-action@v3 | ||
|
||
- name: Login to GitHub Container Registry | ||
run: echo "${{ github.token }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin | ||
|
||
- name: Determine tag | ||
id: tag | ||
run: | | ||
if [[ "${GITHUB_REF#refs/heads/}" == "main" ]]; then | ||
echo "::set-output name=tag::latest" | ||
elif [[ "${GITHUB_REF#refs/heads/}" == "staging" ]]; then | ||
echo "::set-output name=tag::staging" | ||
fi | ||
- name: Build and push | ||
uses: docker/build-push-action@v6 | ||
with: | ||
file: crates/rustfinity-runner/Dockerfile | ||
push: true | ||
tags: | | ||
ghcr.io/${{ github.repository_owner }}/rustfinity-runner:${{ steps.tag.outputs.tag }} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
target/** |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[package] | ||
name = "rustfinity-runner" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
anyhow = "1.0.86" | ||
base64 = "0.22.1" | ||
clap = { version = "4.5.11", features = ["derive"] } | ||
dotenvy = "0.15.7" | ||
duct = "0.13.7" | ||
tokio = { version = "1.39.2", features = ["full"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Stage 1: Clone the repository | ||
FROM alpine/git AS git | ||
WORKDIR /app | ||
RUN git clone https://github.com/dcodesdev/rustfinity.com | ||
|
||
# Stage 2: Build the Runner CLI and the rustfinity.com project | ||
FROM rust:slim-buster | ||
LABEL rustfinity-runner="true" | ||
|
||
# Install OpenSSL development packages and pkg-config | ||
RUN apt-get update && apt-get install -y \ | ||
pkg-config \ | ||
libssl-dev \ | ||
&& rm -rf /var/lib/apt/lists/* | ||
|
||
# Build the Runner CLI | ||
WORKDIR /app/runner | ||
COPY . . | ||
RUN cargo build --release | ||
|
||
# Move the Runner CLI executable | ||
RUN mv target/release/rustfinity-runner /app/ | ||
|
||
# Build the rustfinity.com project | ||
WORKDIR /app/rustfinity.com | ||
COPY --from=git /app/rustfinity.com . | ||
RUN cargo build | ||
|
||
# The final structure: | ||
# /app/rustfinity-runner (executable) | ||
# /app/rustfinity.com/ (project directory) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Stage 1: Clone the repository | ||
FROM alpine/git AS git | ||
WORKDIR /app | ||
RUN git clone -b staging https://github.com/dcodesdev/rustfinity.com | ||
|
||
# Stage 2: Build the Runner CLI and the rustfinity.com project | ||
FROM rust:slim-buster | ||
LABEL rustfinity-runner="true" | ||
|
||
# Install OpenSSL development packages and pkg-config | ||
RUN apt-get update && apt-get install -y \ | ||
pkg-config \ | ||
libssl-dev \ | ||
&& rm -rf /var/lib/apt/lists/* | ||
|
||
# Build the Runner CLI | ||
WORKDIR /app/runner | ||
COPY . . | ||
RUN cargo build --release | ||
|
||
# Move the Runner CLI executable | ||
RUN mv target/release/rustfinity-runner /app/ | ||
|
||
# Build the rustfinity.com project | ||
WORKDIR /app/rustfinity.com | ||
COPY --from=git /app/rustfinity.com . | ||
RUN cargo build | ||
|
||
# The final structure: | ||
# /app/rustfinity-runner (executable) | ||
# /app/rustfinity.com/ (project directory) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Rustfinity code runner | ||
|
||
The official code runner used in [Rustfinity.com](https://www.rustfinity.com), a platform to learn Rust programming language. | ||
|
||
## How to use | ||
|
||
It's best to run this in a docker container to be completely isolated from the outside world. | ||
|
||
1. Build the image locally | ||
|
||
```sh | ||
make build TAG=latest | ||
``` | ||
|
||
2. Convert your code to **base64** format. | ||
|
||
In JavaScript it would be something like this | ||
|
||
```js | ||
const code = `fn main() { | ||
println!("Hello, world!"); | ||
}`; | ||
|
||
const base64Code = Buffer.from(code).toString("base64"); | ||
``` | ||
|
||
3. Run the code using the CLI | ||
|
||
```bash | ||
docker run -i \ | ||
--rm \ | ||
--network=none \ | ||
--cpus=1 \ | ||
-m=500m \ | ||
rustfinity-runner \ | ||
/bin/bash -c "/app/rustfinity-runner run --code 'cHViIGZuIGhlbGxvX3dvcmxkKCkgewogICAgcHJpbnRsbiEoIkdvb2Qgam9iLCB5b3UgZGVjb2RlZCBpdCA6RCIpCn0K' --challenge 'printing-hello-world'" | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
TAG ?= staging | ||
|
||
build: | ||
ifeq ($(TAG), staging) | ||
docker build --no-cache -t rustfinity-runner:$(TAG) . -f Dockerfile.staging | ||
else | ||
docker build --no-cache -t rustfinity-runner:$(TAG) . -f Dockerfile | ||
endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
use clap::{Parser, Subcommand}; | ||
|
||
#[derive(Debug, Parser)] | ||
#[clap(about = "CLI for rust code runner", long_about = None)] | ||
pub struct Cli { | ||
#[clap(subcommand)] | ||
pub command: Commands, | ||
} | ||
|
||
#[derive(Debug, Subcommand)] | ||
pub enum Commands { | ||
#[clap(about = "Run and test the code based on the challenge and code provided")] | ||
Run { | ||
#[clap(short, long)] | ||
/// Code base64 encoded | ||
code: String, | ||
|
||
#[clap(short, long)] | ||
/// Challenge slug | ||
challenge: String, | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
use base64::prelude::*; | ||
use duct::cmd; | ||
use std::env; | ||
use std::fs; | ||
use std::path::Path; | ||
|
||
pub async fn run_code(code_base64: &str, challenge: &str) -> anyhow::Result<String> { | ||
let challenges_path = env::var("CHALLENGES_PATH") | ||
// default value in container | ||
.unwrap_or("/app/rustfinity.com/challenges".to_string()); | ||
|
||
let code_utf8 = BASE64_STANDARD.decode(code_base64)?; | ||
|
||
let code = String::from_utf8(code_utf8)?; | ||
|
||
let repo_path = format!("{challenges_path}/{challenge}"); | ||
let repository_path = Path::new(&repo_path).canonicalize()?; | ||
|
||
// write src/lib.rs | ||
let lib_path = repository_path.join("src/lib.rs"); | ||
|
||
fs::write(&lib_path, &code)?; | ||
|
||
let cwd = repository_path | ||
.to_str() | ||
.ok_or(anyhow::anyhow!("Invalid path"))?; | ||
|
||
let output = run_command_and_merge_output("cargo", &["test"], cwd).await?; | ||
|
||
Ok(output) | ||
} | ||
|
||
pub async fn run_command_and_merge_output( | ||
command: &str, | ||
args: &[&str], | ||
cwd: &str, | ||
) -> anyhow::Result<String> { | ||
let output = cmd!(command, args.join(" ")) | ||
.stderr_to_stdout() | ||
.stdout_capture() | ||
.dir(cwd) | ||
// don't care about exit code | ||
.unchecked() | ||
.run()?; | ||
|
||
Ok(String::from_utf8(output.stdout)?) | ||
} |
Oops, something went wrong.