I'll describe my setup to make the problems less abstract, but they don't seem specific to my case.
Context
We have Python-Django backend and a VueJS frontend, each in a repository, with Gitlab-CI configured and deploy using Portainer (using a stack). A commit in the production branch of each repository follows this path:
- commit
- gitlab-ci pipeline:
- build docker image
- test image (frontend is tested against deployed backend)
- tag image as production:latest
- push image back to gitlab registry
- webhook the corresponding service (frontend/backend) in portainer to update the deployed image
- portainer:
- pull image
- deploy
Problems
Deployment synchronization
Imagine we're doing a major change in both frontend and backend, and both will become incompatible with previous versions. So the new versions must be deployed simultaneously.
In our current setup we have to first deploy the backend (what will break the deployed frontend) and then deploy the new frontend, fixing production, but with a "down" period.
Branch dependency for tests
Sometimes when we develop branch feature-1 in the frontend, it must be tested against branch feature-1 from the backend.
In our current setup all the commits in the frontend are tested against the deployed backend (to avoid replicating the backend in CI, only the production API address is used), resulting in false tests results in such cases.
Backend integration tests
When a commit is done to the backend, it can break the frontend.
Currently the backend isn't tested against the frontend (only the other way).
Possible Solutions
For the deployment synchronization problem I thought about creating another repository that would have only one file specifying the versions for frontend and backend that should be deployed. A commit in this repository would result in both Portanier' services webhooks being "curled" for update (backend and frontend). This doesn't guarantee the simultaneous update (one may fail in Portainer and there would be no rollback), but it would be better than current setup.
I'm not sure about what should be used to specify versions here: commit hash, git tag, branch, docker image version... The last maybe avoids having to rebuild and test images, but I think images name and versions are fixed in Portainer' stacks definition, and not easy to update automatically.
For the branch dependency tests I thought about having a file in each repository (frontend and backend) specifying which branch from the backend/frontend to test against. But the CI for each repository would have to replicate the whole deploy environment (running a new backend and frontend to test each frontend commit, for example). This would also allow backend integration tests. Since we're using Docker, that's not very complicated, but will take extra time for each CI pipeline... Also, when the first repository (frontend or backend) is committed, it'll reference a still non existent branch in the other repository, and fail...
These solutions seem awkward to me, specially if these are problems common to CI/CD with Docker. And it can get even uglier when we add more repositories to the mix.
Alternatives?
Thanks for the attention!
(edit: for curious, my current setup was based on this article)