WIP: feat: use compose-go #816

Draft
decentral1se wants to merge 25 commits from fix/492 into main
Owner

An absolutely diabolical rabbit hole that I wouldn't wish on my worst enemy.

Docker never implemented it and so we were stuck using their custom solution for loading compose config files. This led to #492. compose-go has a better API which supports our various use-cases (loading the compose files via a loaded app, loaded recipe or just directly from the FS) and actually implements the compose spec, so it's a big win!

ToDo

  • Unfuck final TODOs
  • Fix unit tests
  • Fix integration tests
    • bail if recipe lint errors and no --chaos
    • does not crash when docker image has no tag
    • detect no volumes to remove
    • remove volumes
    • list volumes
    • remove no volumes
    • remove single volume
    • remove single volume doesn't delete similar name
    • recipe lint
    • release patch bump
    • release new recipe: development release
    • push during release fails
    • release, fail, release: works
    • upgrade patch
    • upgrade minor
    • upgrade and commit
  • WTF API surface for parsing compose configs: in app context, recipe context, no context
  • Manual testing
  • Document migration notes

Notes

  • The version: ... linting rule is going away because it's deprecated
  • We may see a regression in obscure parsing error messages due to this change
An absolutely diabolical rabbit hole that I wouldn't wish on my worst enemy. Docker [never implemented it](https://github.com/docker/cli/pull/4863) and so we were stuck using their custom solution for loading compose config files. This led to https://git.coopcloud.tech/toolshed/abra/issues/492. `compose-go` has a better API which supports our various use-cases (loading the compose files via a loaded app, loaded recipe or just directly from the FS) and actually implements the compose spec, so it's a big win! ### ToDo - [x] Unfuck final TODOs - [x] Fix unit tests - [x] Fix integration tests - [x] `bail if recipe lint errors and no --chaos` - [x] `does not crash when docker image has no tag` - [x] `detect no volumes to remove` - [x] `remove volumes` - [x] `list volumes` - [x] `remove no volumes` - [x] `remove single volume` - [x] `remove single volume doesn't delete similar name` - [x] `recipe lint` - [x] `release patch bump` - [x] `release new recipe: development release` - [x] `push during release fails` - [x] `release, fail, release: works` - [x] `upgrade patch` - [x] `upgrade minor` - [x] `upgrade and commit` - [ ] WTF API surface for parsing compose configs: in app context, recipe context, no context - [ ] Manual testing - [ ] Document migration notes ### Notes * The `version: ...` linting rule is going away because it's deprecated * We may see a regression in obscure parsing error messages due to this change
decentral1se changed title from WIP: feat: use compose-go for compose parsing to WIP: feat: use compose-go 2026-04-04 16:51:13 +00:00
decentral1se force-pushed fix/492 from 7bd9d667a0 to f2e813e2e3 2026-04-04 16:51:16 +00:00 Compare
decentral1se force-pushed fix/492 from f2e813e2e3 to 5eea459bde 2026-04-04 17:20:03 +00:00 Compare
decentral1se force-pushed fix/492 from 5eea459bde to 5cf42a8104 2026-04-04 17:37:19 +00:00 Compare
decentral1se force-pushed fix/492 from 5cf42a8104 to 94624bb16d 2026-04-04 17:39:32 +00:00 Compare
devydave added 17 commits 2026-08-13 23:02:37 +00:00
feat: adds local vm setup that can reach each other
continuous-integration/drone/push Build is passing
4e42d4fb9e
feat: adds running integrations test suite
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
9bd8f4962a
refactor: adjusting hosts generation
continuous-integration/drone/push Build is passing
5e0dac6508
refactor: simplify config and remove hom-manager dependency
continuous-integration/drone/push Build is passing
1ccbb31b70
feat: adds host module
continuous-integration/drone/push Build is passing
5766a25144
fix: remove personal terminal choice
continuous-integration/drone/push Build is passing
a8c8df8604
docs: add setup documentation
continuous-integration/drone/push Build is passing
bb3c7576f8
docs: formatting
continuous-integration/drone/push Build is passing
21dccc895d
docs: more formatting and typo
continuous-integration/drone/push Build is passing
a28cc7afce
fix: deploy labels nil check
continuous-integration/drone/push Build is failing
8c72890a63
devydave added 2 commits 2026-08-14 11:02:52 +00:00
Member

@decentral1se I think the integration tests are fixed.
What does "WTF API surface for parsing compose configs: in app context, recipe context, no context" mean xD

@decentral1se I think the integration tests are fixed. What does "WTF API surface for parsing compose configs: in app context, recipe context, no context" mean xD
Author
Owner

@devydave amazing, well done!

What does "WTF API surface for parsing compose configs: in app context, recipe context, no context" mean xD

It means to try to unify somehow these "we need to parse compose configs" interface.

We have 3 contexts with data in memory when loading compose configs: 1) we have an app (e.g. appPkg.GetAppComposeConfig(composeFiles, app.Env)) 2) we have a recipe (e.g. recipe.GetComposeConfig()) 3) we have neither and we just need to read the file (e.g. loader.LoadCompose(loader.LoadConf{ComposeFiles: composeFiles})).

This is relevant because some completion happens of env vars, or some merging of config files, etc. etc. Can this API surface be made more understandable for our future selves?

This could be a good internal refactor to carry out now while the issue is burning because it is exactly what made this migration so hilariously difficult. I could understand if you want to skip it however. It's up to you. Most of abra was cobbled together moving super fast, so even if this doesn't get done now, it's nice to mark an issue for a future refactor. It will most likely matter for future maintainers.

@devydave amazing, well done! > What does "WTF API surface for parsing compose configs: in app context, recipe context, no context" mean xD It means to try to unify somehow these "we need to parse compose configs" interface. We have 3 contexts with data in memory when loading compose configs: 1) we have an app (e.g. `appPkg.GetAppComposeConfig(composeFiles, app.Env)`) 2) we have a recipe (e.g. `recipe.GetComposeConfig()`) 3) we have neither and we just need to read the file (e.g. `loader.LoadCompose(loader.LoadConf{ComposeFiles: composeFiles})`). This is relevant because some completion happens of env vars, or some merging of config files, etc. etc. Can this API surface be made more understandable for our future selves? This could be a good internal refactor to carry out now while the issue is burning because it is exactly what made this migration so hilariously difficult. I could understand if you want to skip it however. It's up to you. Most of abra was cobbled together moving super fast, so even if this doesn't get done now, it's nice to mark an issue for a future refactor. It will most likely matter for future maintainers.
Member

@devydave amazing, well done!

What does "WTF API surface for parsing compose configs: in app context, recipe context, no context" mean xD

It means to try to unify somehow these "we need to parse compose configs" interface.

We have 3 contexts with data in memory when loading compose configs: 1) we have an app (e.g. appPkg.GetAppComposeConfig(composeFiles, app.Env)) 2) we have a recipe (e.g. recipe.GetComposeConfig()) 3) we have neither and we just need to read the file (e.g. loader.LoadCompose(loader.LoadConf{ComposeFiles: composeFiles})).

This is relevant because some completion happens of env vars, or some merging of config files, etc. etc. Can this API surface be made more understandable for our future selves?

This could be a good internal refactor to carry out now while the issue is burning because it is exactly what made this migration so hilariously difficult. I could understand if you want to skip it however. It's up to you. Most of abra was cobbled together moving super fast, so even if this doesn't get done now, it's nice to mark an issue for a future refactor. It will most likely matter for future maintainers.

I agree with that, while fixing the remaining tests it was quite confusing having multiple places where compose files are parsed.
I will take a look, if I can add unify the parsing, that can be simply adjusted by the caller.

> @devydave amazing, well done! > > > What does "WTF API surface for parsing compose configs: in app context, recipe context, no context" mean xD > > It means to try to unify somehow these "we need to parse compose configs" interface. > > We have 3 contexts with data in memory when loading compose configs: 1) we have an app (e.g. `appPkg.GetAppComposeConfig(composeFiles, app.Env)`) 2) we have a recipe (e.g. `recipe.GetComposeConfig()`) 3) we have neither and we just need to read the file (e.g. `loader.LoadCompose(loader.LoadConf{ComposeFiles: composeFiles})`). > > This is relevant because some completion happens of env vars, or some merging of config files, etc. etc. Can this API surface be made more understandable for our future selves? > > This could be a good internal refactor to carry out now while the issue is burning because it is exactly what made this migration so hilariously difficult. I could understand if you want to skip it however. It's up to you. Most of abra was cobbled together moving super fast, so even if this doesn't get done now, it's nice to mark an issue for a future refactor. It will most likely matter for future maintainers. I agree with that, while fixing the remaining tests it was quite confusing having multiple places where compose files are parsed. I will take a look, if I can add unify the parsing, that can be simply adjusted by the caller.
devydave added 5 commits 2026-08-14 16:14:48 +00:00
Member

@devydave amazing, well done!

What does "WTF API surface for parsing compose configs: in app context, recipe context, no context" mean xD

It means to try to unify somehow these "we need to parse compose configs" interface.

We have 3 contexts with data in memory when loading compose configs: 1) we have an app (e.g. appPkg.GetAppComposeConfig(composeFiles, app.Env)) 2) we have a recipe (e.g. recipe.GetComposeConfig()) 3) we have neither and we just need to read the file (e.g. loader.LoadCompose(loader.LoadConf{ComposeFiles: composeFiles})).

This is relevant because some completion happens of env vars, or some merging of config files, etc. etc. Can this API surface be made more understandable for our future selves?

This could be a good internal refactor to carry out now while the issue is burning because it is exactly what made this migration so hilariously difficult. I could understand if you want to skip it however. It's up to you. Most of abra was cobbled together moving super fast, so even if this doesn't get done now, it's nice to mark an issue for a future refactor. It will most likely matter for future maintainers.

I agree with that, while fixing the remaining tests it was quite confusing having multiple places where compose files are parsed.
I will take a look, if I can add unify the parsing, that can be simply adjusted by the caller.

After looking into it, the loading pattern of compose file is messy overall, I think it is the best to move it to a separate issue.

> > @devydave amazing, well done! > > > > > What does "WTF API surface for parsing compose configs: in app context, recipe context, no context" mean xD > > > > It means to try to unify somehow these "we need to parse compose configs" interface. > > > > We have 3 contexts with data in memory when loading compose configs: 1) we have an app (e.g. `appPkg.GetAppComposeConfig(composeFiles, app.Env)`) 2) we have a recipe (e.g. `recipe.GetComposeConfig()`) 3) we have neither and we just need to read the file (e.g. `loader.LoadCompose(loader.LoadConf{ComposeFiles: composeFiles})`). > > > > This is relevant because some completion happens of env vars, or some merging of config files, etc. etc. Can this API surface be made more understandable for our future selves? > > > > This could be a good internal refactor to carry out now while the issue is burning because it is exactly what made this migration so hilariously difficult. I could understand if you want to skip it however. It's up to you. Most of abra was cobbled together moving super fast, so even if this doesn't get done now, it's nice to mark an issue for a future refactor. It will most likely matter for future maintainers. > > I agree with that, while fixing the remaining tests it was quite confusing having multiple places where compose files are parsed. > I will take a look, if I can add unify the parsing, that can be simply adjusted by the caller. After looking into it, the loading pattern of compose file is messy overall, I think it is the best to move it to a separate issue.
Author
Owner

Great, go ahead and feel free to merge stuff, take the lead, open issues, etc. You don't need to ask.

For releaseing abra when you feel like things are stable, there are these docs:

https://docs.coopcloud.tech/abra/hack/#release-management

Thanks!

Great, go ahead and feel free to merge stuff, take the lead, open issues, etc. You don't need to ask. For releaseing abra when you feel like things are stable, there are these docs: > https://docs.coopcloud.tech/abra/hack/#release-management Thanks!
All checks were successful
continuous-integration/drone/push Build is passing
This pull request has changes conflicting with the target branch.
  • go.mod
  • go.sum
  • pkg/i18n/locales/es.mo
  • pkg/i18n/locales/es.po
  • vendor/modules.txt
This pull request is marked as a work in progress.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin fix/492:fix/492
git checkout fix/492
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: toolshed/abra#816