Benezivas / algobattle

Let teams compete by making them create hard instances and fast solvers for problems of your choice. Then pitch these instances and solvers against one another. All language-agnostic.
https://algobattle.org
MIT License
8 stars 3 forks source link

Allow for shared implementations #168

Open UnlimitedCookies opened 2 days ago

UnlimitedCookies commented 2 days ago

Due to the high similarity of both the solver and generator it seems reasonable to create a shared directory at the generator and solver directory level. Due to the Dockerfile being inside the generator and solver directory, it does not allow for COPYing the shared directory into the newly built container (resulting in a "COPY failed: forbidden path outside the build context: ../shared ()").

I'm currently unsure what might be a good solution.

ImogenBits commented 2 days ago

What you're asking for cannot be done directly. Due to the way that Docker works it requires every file used in the build to be contained in a single top level folder called the build context. When using Docker directly you could set the build context to be the entire project folder containing generator, solver, and shared, but that cannot be done within Algobattle and also cannot implemented due to the way it is implemented. You also cannot use symlinks to get the folder structure you want to work.

However, there is a way to work with your use case, even though it has some downsides. Let's say you start with a folder structure like this:

Pairsum
 ├─ generator/
 │  ├─ unique_data.json
 │  └─ Dockerfile
 ├─ results/
 ├─ solver/
 │  ├─ unique_data.json
 │  └─ Dockerfile
 ├─ shared/
 │  └─ shared_data.json
 ├─ .gitignore
 ├─ algobattle.toml
 ├─ description.md
 └─ problem.py

What we can do is just move everything inside all of generator, solver, and shared into a single folder, giving everything a unique name and possibly moving things that aren't the dockerfiles into subdirectories:

Pairsum
 ├─ everything/
 │  ├─ generator.dockerfile
 │  ├─ generator/
 │  │  └─ unique_data.json
 │  ├─ solver.dockerfile
 │  ├─ solver/
 │  │  └─ unique_data.json
 │  └─ shared_data.json
 ├─ results/
 ├─ .gitignore
 ├─ algobattle.toml
 ├─ description.md
 └─ problem.py

And then edit the algobattle.toml to reflect the new paths of our dockerfiles (in particular, the path to the files itself, not just their parent folder):

# other stuff above this
[teams."Red Pandas"]
generator = "everything/generator.dockerfile"
solver = "everything/solver.dockerfile"

Of course, you will then also want to adapt your dockerfiles to look for everything in the new paths.

There are two important things to note here. The first is that the dockerfiles must be in the folder that contains everything used in the builds and it must have the .dockerfile extension. That is, they cannot be placed in the everything/generator or everything/solver subdirectories. And while they can be named something like my very fancy name.dockerfile, it must always carry that extension or it will not be recognised by Algobattle.

The second is that when you package an Algobattle project and upload it to the server, it will always bundle the entire build context together. It isn't possible to determine that some folders might not be needed for the generator or solver builds, so you would end up duplicating this data. If these are only a couple of light code files that isn't an actual issue, but if you accidentally leave things like build artifacts or precompiled binaries (which is bad practice in the first place) in the folders before packaging, you will create rather large files unnecessarily.