-
Epic
-
Resolution: Obsolete
-
Major
-
None
-
rhos-18.0.0
-
None
-
Automatically bump dependencies on stable/release-proposed branches
-
False
-
-
False
-
Not Selected
-
Proposed
-
Proposed
-
Done
-
Proposed
-
Proposed
-
Rejected
-
-
-
Moderate
What to bump
There are different set of dependencies to keep up to date for each operator:
- external dependencies (e.g. k8s.io, gomega, etc)
- lib-common
- other operators /api(s) module
Current solution on the main branch
- external dependencies: All of them are tracked via semver tags and updated by renovate. We have semver version pins for certain dependencies e.g. k8s.io < 0.29.
- both lib-common and operator api(s) dependencies are tracked via gomod pseudoversion and updated via renovate by always bumping to latest commit returned by https://api.github.com/repos/openstack-k8s-operators/<repo>/commits
Expected behavior on stable/release-proposed branches
- freeze the external dependencies. This can be done by adding a semver version pin to the branch specific renovate configuration and keep using renovate.
- still update the lib-common and operator api(s) dependencies but instead of taking the latest commit from main, take the latest commit of the matching branch. E.g. on 18.0.0-proposed used the latest lib-common from 18.0.0-proposed. Renovate cannot do this.
Problem
Renovate cannot really handle gomod pseudoversions. It only has a fallback to update a dependency by git digest (i.e. git hash) taking the last commit from github (from the github default branch) and inputting that to go mod to resolve into pseudoversion. See the code
Also the go version resolution ecosystem (a.k.a. goproxy) only handles a single stream of pseudoversions via @latest. There is no way to express that we need the latest from a specific branch, or a latest since a specific tag (even though this can be expressed with go pseudoversions). See doc
Proposed solution
- Keep using renovate on main as today
- Do not automatically bump external dependencies on <release>-proposed branches as bump is rarely needed for these deps on these branches.
What to do with lib-common and operator api(s) deps on <release>-proposed branches:
- Option A: Do not implement automatic bumping.
- We manually bumped necessary dependencies on 18.0.0-proposed so it is doable.
- However as this is manual work it is easy to forget and it is error prone.
- Option B: Implement and maintain a script that:
- runs periodically (probably called in our renovate runner VM the same way as we call renovate)
- calculates necessary bumps for each <release>-proposed branch (e.g. with go get github.com/<dependency>@<rbranch-name>)
- creates and maintains PRs for these version bumps in github (very similarly how renovate does it)
This can be a costly re-implementation of generic renovate logic (e.g. PR management)
- Option C: Hack the dependency version in a renovate post task
- A post task can be any script in renovate that run after renovate generate the bump. With a post task using go get github.com/<dependency>@<branch-name> we could override what renovate generated while still using the renovate infrastructure to manage bump PRs.
- It is a hack that goes against what renovate knows and wants to do. We can hide most of the discrepancies (e.g. by changing the commit message / PR template), but long term this feels dangerous.
- Option D: We extend renovate to do what we want.
- That feels a huge undertaking
- Option E: Start tagging commits in lib-common and operator api(s) module that we want to consume from other operators
- Then we can designate a minor version to a release-proposed branch and let renovate just follow that minor version via a minor version pin
- This needs a lot more tagging than what we did so far.
- Option F: Move all our openstack-k8s-operator module into a single repository
- It is a big move
- Dependencies within that repo automatically handled by git branching no renovate and no manual pinning is needed.
- Option G: Move the openstack-k8s-operator api(s) moduel into a single repository, keep the main operator modules and lib-common separate.
- Similar strategy than Option F but a smaller move
- cross api(s) module dependencies not need to be bumped any more
- lib-common still needs to be bumped and need one of the other options applied, e.g. tagging every change.
Details of options with interest
Option C: Hack the dependency version in a renovate post task
Here is a simplified example how this could work. The example consist of two repos example-lib, and example-service. Both has two branches main (default), and stable. Both has a single go module. The example-service depends on the example-lib. The example-service has renovate.json file on both main and stable branch.
- example-service@main renovate.json: https://github.com/gibizer/example-service/blob/ecac9923dbe65e93bab096362c0e6a3657eed1ea/renovate.json
It is a basic config, nothing new here. It allows renovate to bump example-lib to latest all the time. And allows renovate to inspect the renovate.json on the stable branch for stable specific rules- This config generates a normal bump PR for main: https://github.com/gibizer/example-service/pull/4
- example-service@stable renovate.json: https://github.com/gibizer/example-service/blob/47b802de7f782635752e0b708148af023489ce08/renovate.json
- The go get command ensures that whatever bump renovate generates is rewritten to only bump to the latest commit of the example-lib@stable
"postUpgradeTasks": { "commands": ["go get github.com/gibizer/example-lib@stable", "go mod tidy"],
- As the command override the content of generated commit, the commit message and PR message needs to be massaged to hide the discrepancy that renovate thinks it bumps to example-lib@main not example-lib@stable:
"commitMessageExtra": "", "prBodyColumns": ["Package"],
- This config result in a PR with a proper content and a limited PR message: https://github.com/gibizer/example-service/pull/6
- The go get command ensures that whatever bump renovate generates is rewritten to only bump to the latest commit of the example-lib@stable
*NOTE*:
- on @sable renovate will only generate a commit and therefore run our special post task if there is a bump opportunity for example-lib@main. Hopefully we can assume the main will always be ahead of stable.
- if there is a bump opportunity to example-lib@main but there is no new change to bump to on example-lib@stable then our special post task will make the commit empty. We need to see how renovate will react to this situation.
- links to
- mentioned on