From 04dc8c25d9e8d3965a369bd08f7d9d7d3bcf1cc2 Mon Sep 17 00:00:00 2001
From: Orestis <orestis.malaspinas@pm.me>
Date: Wed, 20 Sep 2023 17:23:18 +0200
Subject: [PATCH] format

---
 Wiki/CLI-assignment-creation.md | 414 ++++++++++++++++++++++++++++++++
 1 file changed, 414 insertions(+)
 create mode 100644 Wiki/CLI-assignment-creation.md

diff --git a/Wiki/CLI-assignment-creation.md b/Wiki/CLI-assignment-creation.md
new file mode 100644
index 0000000..1644129
--- /dev/null
+++ b/Wiki/CLI-assignment-creation.md
@@ -0,0 +1,414 @@
+# How to create an assignment
+
+We will describe how to create a very simple assignment with dojo.
+
+Here we will build a `Hello world!` in the C programming language. We will describe how one must
+modify the default template to have an exercise.
+
+The exercise will be to fill a function to return the `Hello world!` string.
+The output of the function will be printed on the standard output.
+The structure will be provided to the students as well as a very simple `Makefile`
+to compile and run the code.
+
+The success or failure of this assignment will be tested by comparing the output
+of our program with an the expected output (the famous `Hello world!`).
+
+To build this exercise we need to perform several steps that will be described below in great details.
+
+## Empty assignment creation
+
+First create a new assignment with the command
+```bash
+$ dojo assignment create --name c_hello_world
+```
+```console
+Please wait while we verify and retrieve data...
+ℹ Checking Dojo session: 
+    ✔ The session is valid
+        ✔ Teaching staff permissions
+ℹ Checking Gitlab token: 
+    ✔ Read access
+    ✔ Write access
+✔ Assignment name "c_hello_world" is available
+Please wait while we are creating the assignment...
+✔ Assignment successfully created
+    ℹ Name: c_hello_world
+    ℹ Web URL: https://gitedu.hesge.ch/dojo/assignment/c_hello_world
+    ℹ HTTP Repo: https://gitedu.hesge.ch/dojo/assignment/c_hello_world.git
+    ℹ SSH Repo: ssh://git@ssh.hesge.ch:10572/dojo/assignment/c_hello_world.git
+```
+
+## Clone the assignment locally
+
+The assignment is nothing more than a git repository. We just clone it and start
+modifying it
+```bash
+$ git clone ssh://git@ssh.hesge.ch:10572/dojo/assignment/c_hello_world.git
+```
+```console
+Cloning into 'c_hello_world'...
+remote: Enumerating objects: 18, done.
+remote: Counting objects: 100% (18/18), done.
+remote: Compressing objects: 100% (12/12), done.
+remote: Total 18 (delta 3), reused 18 (delta 3), pack-reused 0
+Receiving objects: 100% (18/18), 4.37 KiB | 4.37 MiB/s, done.
+Resolving deltas: 100% (3/3), done.
+```
+The `c_hello_world` assignment has now the following structure
+```bash
+$ tree c_hello_world/
+```
+```console
+c_hello_world/
+├── docker-compose.yml
+├── Dockerfile
+├── dojo.assignment
+└── README.md
+```
+
+## Build the development environment
+
+In order to execute a C program we need a working compiler and `make`. In order to
+produce a special result file to be parsed by the `dojo` tool to produce nicely formatted output
+we will use `jq`, a command-line json creation/edition/reding tool. Our `Dockerfile`
+contains
+```dockerfile
+FROM ubuntu:latest
+RUN apt update && apt install gcc make jq -y
+COPY . /
+ENTRYPOINT ["./run.sh"]
+```
+We see that we start by installing the required packages on top of the latest Ubuntu image.
+We then proceed to copy the complete assignment into the docker container, finall we run
+a yet to be created `run.sh` script.
+
+We can test our `Dockerfile` by running the command
+```bash
+$ docker compose run --build hello_world
+```
+```console
+[+] Building 20.5s (8/8) FINISHED                                 
+ => [hello_world internal] load build definition from Dockerfile
+ => => transferring dockerfile: 134B
+ => [hello_world internal] load .dockerignore
+ => => transferring context: 2B
+ => [hello_world internal] load metadata for docker.io/library/ubuntu:latest
+ => CACHED [hello_world 1/3] FROM docker.io/library/ubuntu:latest@sha256:ec050c32e4a6085b423d36ecd025c0d3ff00c38ab93a3d71a460ff1c44fa6d77
+ => [hello_world internal] load build context
+ => => transferring context: 39.87kB
+ => [hello_world 2/3] RUN apt update && apt install gcc make jq -y
+ => [hello_world 3/3] COPY . /
+ => [hello_world] exporting to image
+ => => exporting layers
+ => => writing image sha256:4b561113c7123da08206a2cf2642cb4f331670fe44350646437eaa78e44aff3a
+ => => naming to docker.io/library/c_hello_world-hello_world
+ERRO[0021] error waiting for container:                                   
+Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "./run.sh": stat ./run.sh: no such file or directory: unknown
+```
+We see an error at the end of the command which is perfectly normal. We did not create the `run.sh` file et (let's leave that for later).
+
+We then need to focus on the `docker-compose.yml` file which will take care of all the hard work
+needed if complex workflows are required. Here it is as simple as possible and should contain
+```yml
+services:
+    hello_world:
+        container_name: hello_world
+        build:
+            context: ./
+            dockerfile: Dockerfile
+        volumes:
+            - hello_world_volume:/result # <hello_world_volume> must be the same as below but
+                                         # the name may be arbitrary. This volume must be 
+                                         # present in the dojo_assignment.json file under the field
+                                         # "result": {
+                                         #   "volume": "hello_world_volume", 
+                                         #    ...
+                                         # }
+volumes:
+    hello_world_volume:
+```
+In this file, we see the definition of a `hello_world_volume` this is an arbitrary name and can be changed but it
+must be coherent in this file and in the `dojo_assignment.json` file (more on this later configuration file in [The dojo configuration file](#the-dojo-configuration-file)).
+This volume is responsible of mounting `/result/` directory which will contain all
+the output generated by our assignment (again the name can be changed). In particular
+in this director e will be required to create a `dojo_assignment.json` file
+that contains at least if the assignment was successfully performed (more on that at the end of the [Creating the assignment files](#creating-the-assignment-files) section).
+
+## The dojo configuration file
+
+The `dojo_assignment.json` file contains the general configuration of the assignment. 
+The important configuration parameters are:
+- the *immutable files* which are files that will be overwritten when the compilation pipeline is run (even if the student
+modifies these files the modifications will not be taken into account),
+- the *results* which is the volume corresponding to the `docker-compose.yml` file.
+
+In its default form `dojo_assignment.json` file contains
+```json
+{
+  "dojoAssignmentVersion": 1,
+  "version": 1,
+  "immutable": [
+    {
+      "description": "Dockerfile of the unique container",
+      "path": "Dockerfile",
+      "isDirectory": false
+    }
+  ],
+  "result": {
+    "container": "hello_world",
+    "volume": "hello_world_volume"
+  }
+}
+```
+Here we see only one immutable file which is the `Dockerfile` (the `isDirectory` field is `false` but it is possible to make
+complete directories immutable) and we see that:
+* the value of the `container` field (`hello_world`) corresponds to
+the value of the `container_name` field in the `docker-compose.yml` file,
+* the value of the `volume` field (`hello_world_volume`) corresponds to the `volumes` field in the `docker-compose.yml` file.
+
+This file will be completed in [The immutable files](#the-immutable-files) sectino with the files of our assignment that will be
+created in the [next section](#creating-the-assignment-files).
+
+## Creating the assignment files
+
+For this assignment we will create the following files with the following content:
+
+- `src/Makefile`
+```makefile
+CC:=gcc
+CFLAGS:=-Wall -Wextra -Wpedantic -fsanitize=address  -Werror -g
+LDFLAGS:=-fsanitize=address
+
+hello_world: hello_world.o function.o
+	gcc -o $@ $^ $(LDFLAGS)
+
+hello_world.o: function.h
+
+function.o: function.h
+
+run: hello_world
+	./hello_world
+
+clean: 
+	rm -f *.o hello_world
+```
+- `src/hello_world.c`
+```c
+#include <stdio.h>
+#include <stdlib.h>
+#include "function.h"
+
+int main()
+{
+    printf("%s", hello_world());
+    return EXIT_SUCCESS;
+}
+```
+- `src/function.h`
+```c
+#ifndef _FUNCTION_H_
+#define _FUNCTION_H_
+
+char *hello_world();
+
+#endif
+```
+- `src/function.c`
+```c
+#include "function.h"
+
+char *hello_world()
+{
+    // TODO: Replace 0 here to return "Hello world!"
+    return 0;
+}
+```
+- `src/expected_output.txt`
+```
+Hello world!
+```
+
+These files will be used to create an executable that will be run by the custom execution script, `run.sh`, see the `Dockerfile` in
+the [Build the environment](#build-the-development-environment) section.
+
+All these files have arbitrary names and it's completely up to the teacher to make a coherent exercise.
+
+The only missing file is `run.sh` (do not forget to make it executable, `chmod +x run.sh`) that contains the following code
+```bash
+#!/bin/bash
+
+echo "Starting tests."
+
+GLOBAL_SUCCESS=false
+
+make -C src clean -s
+make -C src -s
+if [ $? -eq 0 ]; then
+    make run -C src > src/output.txt -s
+    if [ $? -eq 0 ]; then
+        diff --color src/output.txt src/expected_output.txt > result/diff_output.txt
+        if [ $? -ne 0 ]; then
+            echo "Output is wrong:";
+            cat result/diff_output.txt
+        else
+            echo "All tests were a complete success"
+            GLOBAL_SUCCESS=true
+        fi
+        
+    else
+        echo "Execution failed";
+    fi
+else
+    echo "Compilation failed."
+fi
+
+jq --null-input --arg success $GLOBAL_SUCCESS \
+    '{"success": $success | test("true")}' > /result/results.json
+```
+Here one can see the creation of two different files that are located in the `result` directory:
+- `result/results.json`
+- `result/diff_output.txt`
+The `results.json` is mandatory to be created and must at least contain the
+`success` field must be `true` or `false` and determines whether the
+assignment is a success or a failure. The other files present in the `result` folder
+can be retrieved by the students.
+
+To test if everything works according to plan, one can again use the command
+```bash
+$ docker compose run --build hello_world
+```
+```console
+[+] Building 1.8s (8/8) FINISHED                                                                                    
+ => [hello_world internal] load build definition from Dockerfile
+ => => transferring dockerfile: 134B
+ => [hello_world internal] load .dockerignore
+ => => transferring context: 2B
+ => [hello_world internal] load metadata for docker.io/library/ubuntu:latest
+ => [hello_world 1/3] FROM docker.io/library/ubuntu:latest@sha256:ec050c32e4a6085b423d36ecd025c0d3ff00c38ab93
+ => [hello_world internal] load build context
+ => => transferring context: 3.23kB
+ => CACHED [hello_world 2/3] RUN apt update && apt install gcc make jq -y
+ => [hello_world 3/3] COPY . /
+ => [hello_world] exporting to image
+ => => exporting layers
+ => => writing image sha256:5499aa3aa0b2f2021584dbf46b4b05ab83dc0a5ad4d6c81a3466c56673c3f562
+ => => naming to docker.io/library/c_hello_world-hello_world
+Starting tests.
+Output is wrong:
+1c1
+< (null)
+\ No newline at end of file
+---
+> Hello world!
+\ No newline at end of file
+```
+where we see that the execution fails. This will be improved in the future and the actual execution as expected to be
+run by the students will be added.
+
+## The immutable files
+
+There is only one file that should be modified by the students in this example: the `function.c` file. Therefore we can safely
+add all the created files in the `src` except `src/function.c` which is precisely
+the file that the student must modify, as well as the `run.sh` file. The `dojo_assignment.json` file becomes
+```json
+{
+  "dojoAssignmentVersion": 1,
+  "version": 1,
+  "immutable": [
+    {
+      "description": "Dockerfile of the unique container",
+      "path": "Dockerfile",
+      "isDirectory": false
+    },
+    {
+      "description": "The entry point of the Dockerfile",
+      "path": "run.sh",
+      "isDirectory": false
+    },
+    {
+      "description": "The makefile for compilation/execution purposes",
+      "path": "src/Makefile",
+      "isDirectory": false
+    },
+    {
+      "description": "Entry point of the code",
+      "path": "src/hello_world.c",
+      "isDirectory": false
+    },
+    {
+      "description": "The header file fot the program's assignment",
+      "path": "src/function.h",
+      "isDirectory": false
+    },
+    {
+      "description": "The expected output file for comparing with the actual output",
+      "path": "src/expected_output.txt",
+      "isDirectory": false
+    }
+  ],
+  "result": {
+    "container": "hello_world",
+    "volume": "hello_world_volume"
+  }
+}
+```
+
+## The `README.md` file
+
+The `README.md` file is used to provide informations on the assignment and the way the teacher wants students to accomplish
+the assignment and its content is completely free. It is recommended to use the `Markdown` syntax as the
+file extension suggests.
+
+In this assignment the `README.md` file reads
+```markdown
+# Hello world!
+
+C'est le premier vrai exercice jamais créé sur le Dojo!
+
+Il sert de tutoriel pour créer un exercice simple en C.
+
+## But
+
+Le but est de faire afficher "Hello world!" à notre programme en C.
+
+Pour ce faire, il faut modifier le fichier `src/function.c` sous la ligne
+annotée avec `TODO`. Bonne chance!
+```
+
+## Publish the work
+
+Now that the assignment is ready, we must publish it. First add/commit/push all the
+files needed for your exercise. In this case, it should be:
+```console
+c_hello_world/
+├── docker-compose.yml
+├── Dockerfile
+├── dojo_assignment.json
+├── README.md
+├── run.sh
+└── src
+    ├── expected_output.txt
+    ├── function.c
+    ├── function.h
+    ├── hello_world.c
+    └── Makefile
+```
+Then one must *publish* the assignment for the students to be able to perform to get the exercise.
+
+```bash
+$ dojo assignment publish c_hello_world
+```
+```console
+? Are you sure you want to publish this assignment? Yes
+Please wait while we verify and retrieve data...
+ℹ Checking Dojo session: 
+    ✔ The session is valid
+ℹ Checking assignment:
+    ℹ c_hello_world
+        ✔ The assignment exists
+        ✔ You are in the staff of this assignment
+Please wait while we publish the assignment...
+✔ Assignment c_hello_world successfully published
+```
+
+The assignment is now ready to be performed by students!
-- 
GitLab