Description
Motivation
As projects managed by vagga get bigger, we need more tools to manage them easily. Here is a set of ideas in unified discussion to find out how they fit together.
Proposal
1. Using Commands From Different Mixins
When there was only one file we could use anchors to refer to the commands defined elsewhere, but when using mixins we can't. This is mostly useful for supervise commands.
This is #466, but using shorter !Ref
syntax:
commands:
run-a-database: !Command # ...
other-cmd: !Supervise
children:
db: !Ref run-a-database
2. More powerful pipelines
Currently we have:
prerequisites
to run commands sequentially!Supervise
to run commands in parallel
But what we really want is more than that:
- Run a database, wait for become available then start the app
- Run database, run migration suite, start the app
- Run few test suites in parallel
- Run many iterations of test suite
And all the combinations of above. This is a tough problem to solve, but let's imagine we can draw
a diagram:
run: !Supervise
pipeline: |
[ mkdirs ]
[ ----------- db ------------ ]
[ ----------- cache --------- ]
[ wait-db ]
[ migration ]
[ ----- wait-cache --- ]
[ app ]
children:
db: !Command
cache: !Command
wait-db: !Command
wait-cache: !Command
migration: !Command
app: !Command
Or maybe using a graph (dot-like syntax, where arrow ->
means "depends on", or "after"):
run: !Supervise
dependencies: |
{db, cache} -> mkdir
migration -> wait-db
app -> {wait-db, wait-cache, migration}
children:
db: !Command
cache: !Command
wait-db: !Command
wait-cache: !Command
migration: !Command
app: !Command
3. Subprojects
Mixins and subconfigs are great for reusing parts of configs from elsewhere, but they only work when target config is specifically prepared to be sourced. For example, they don't change where /work
dir point to. Also subconfigs don't handle commands at all, while mixins handle command conflicts by overriding commands (which is fine for them but not for cross-project embedding).
So this issue proposes subprojects
:
subprojects:
db: ./cookbook/postgres
images: ./services/pixel
commands:
run: !Supervise
prerequisites: [db:migration]
children:
db: !Ref db:run
images: !Ref images:run
app: !Command # ...
In this case !Ref db:run
and db:migration
work exactly the same as if you would run vagga run
or vagga migration
in the cookbook/postgres
directory, but allows commands to be used as part of a higher level pipeline.
The subprojects here are just subdirectories. It's expected that they are git submodules in most cases, but no such obligations are done.
One of the questions here is how .vagga
folder is managed here? Are these projects glued together, or work exactly as cd'ing into a directory? Separate dirs work with a least surprise for user. While single directory is probably faster and more space-efficient, still having more edge-cases though.
4. Workspaces
The idea is that subprojects should be great, but we also want loose coupling.
Let's imagine we have services B and C depend on A. They both probably have A
as a subproject. But then we have a superproject which contains all the A, B, and C. And at a glance it looks like A will be duplicated three times.
This is easy to overcome if you have only one "superproject". Just don't use subprojects for inner
project and run anything that involves more than one project in a top level thing. This doesn't work well for integration tests though.
So the idea here is probably to have a parent directory for multiple projects and to remap their subprojects to different folders. I.e. workspace/B/A
should be mapped to workspace/A
, it's easy
to do inside vagga using bind mounts.
While it looks so simple the real questions of how to organize workspace, is it versioned, how to match common subprojects, how to manage git submodules, and so on. So probably we should postpone it until we have more usecases for subprojects to find good solution to the problem.