Codeberg/Contributing
26
57
Fork
You've already forked Contributing
9

[Intro] Hosted renovate-bot #47

Closed
opened 2024年02月11日 13:20:58 +01:00 by pat-s · 19 comments
Member
Copy link

About yourself

Picking up the discussions in Codeberg/Community#1108 and Codeberg/Community#799, I'd like to propose to run and maintain a renovate-bot for all users on CB (via opt-in).

Details

(TBD, just an initial proposal)

  • The bot runs renovate defaults and users are encouraged to use repo-specific config files
  • The bot runs every 8 hours (3 am UTC, 11 am UTC, 19 UTC) (to avoid using excessive resources)
  • The implementation would need to use both a repository cache and a dependency cache (redis)
  • Users acknowledge that the bot user (and hence also all people which maintain it) possible have read/write access to repositories the bot has access to
  • Users acknowledge that they can't change/control the bot frequency
  • The config repo would live in the Codeberg org and users can open issues there

Interests

  • Software development
  • Community support
  • Public Relations
  • Infrastructure
  • Organization (team meetings, events etc)
  • Other (see text above)

Quick checks

  • I... work on a project on my own
  • ... join an existing team
  • ... start something new
  • ... learn something for yourself
  • ... dedicate a steady amount of time
  • ... work on a project for a limited period
### About yourself Picking up the discussions in https://codeberg.org/Codeberg/Community/issues/1108 and https://codeberg.org/Codeberg/Community/issues/799, I'd like to propose to run and maintain a renovate-bot for all users on CB (via opt-in). ## Details (TBD, just an initial proposal) - The bot runs renovate defaults and users are encouraged to use repo-specific config files - The bot runs every 8 hours (3 am UTC, 11 am UTC, 19 UTC) (to avoid using excessive resources) - The implementation would need to use both a [repository cache](https://docs.renovatebot.com/self-hosted-configuration/#repositorycachetype) and a [dependency cache (redis)](https://docs.renovatebot.com/self-hosted-configuration/#redisurl) - Users acknowledge that the bot user (and hence also all people which maintain it) possible have read/write access to repositories the bot has access to - Users acknowledge that they can't change/control the bot frequency - The config repo would live in the `Codeberg` org and users can open issues there ### Interests - [ ] Software development - [ ] Community support - [ ] Public Relations - [x] Infrastructure - [ ] Organization (team meetings, events etc) - [ ] Other (see text above) ### Quick checks - [ ] I... work on a project on my own - [ ] ... join an existing team - [x] ... start something new - [ ] ... learn something for yourself - [ ] ... dedicate a steady amount of time - [ ] ... work on a project for a limited period

Funny, I just thought about doing this today too 😄

What infrastructure were you planning on backing the bot with?

Funny, I just thought about doing this today too 😄 What infrastructure were you planning on backing the bot with?
Owner
Copy link

We can provision an LXC container on Codeberg's infrastructure. You need to tell us about hardware requirements (RAM + CPU and optionally storage explanations in case you need large amounts of storage) and provide us with SSH keys.

If you need web access, you need to ask for a subdomain and give us the correct port (we do tls termination and forward unencrypted traffic by default, but you can also do tls termination yourself if you prefer).

We can provision an LXC container on Codeberg's infrastructure. You need to tell us about hardware requirements (RAM + CPU and optionally storage explanations in case you need large amounts of storage) and provide us with SSH keys. If you need web access, you need to ask for a subdomain and give us the correct port (we do tls termination and forward unencrypted traffic by default, but you can also do tls termination yourself if you prefer).

Regarding this Codeberg-Infrastructure/configuration-as-code#12 (comment) and just repeating something I said on matrix;

one way to have an opt-in approach would be to make the bot account restricted, which will prevent it from automatically having read access to public repos. This means that the list of repos the bot is checking will be limited to only those that have explicitly given renovate read permissions (either at the org level or the repo level).

I expect this to significantly reduce the load on the infra hosting renovate, since it would no longer be checking the files of basically every repo on CB, and possibly the receiving end too (Codeberg API).

Regarding Otto's comment here Codeberg/Community#799 (comment),

I recall that Renovate wasn't very efficient?

From anecdotal experience running it on my personal forgejo instance, this feels... unfortunately very much like the case. It varies wildly based on repo-specific config; sometimes operating on 7-8 repos will take upwards of 10 minutes (serially) if, for example, dependencyDashboardOSVVulnerabilitySummary is enabled. In that particular case, I also had to bump the memory limit of that job up to 1Gi - 1Gi of RAM per 8 repos is... not very scalable even if this is the worst case scenario.

If 8 hours somehow isn't enough to process the whole of CB, we could possibly consider somehow dividing up the namespace and parallelising. That said, I'm more concerned about RAM or (possibly) disk usage, depending on how the cache is structured; I want to observe renovate's behaviour some more before even trying to estimate limits :/

Regarding this https://codeberg.org/Codeberg-Infrastructure/configuration-as-code/issues/12#issuecomment-1514515 and just repeating something I said [on matrix](https://matrix.to/#/!wkyjxWeAOBpKMvHbno:matrix.org/$gsF6euHnZkDBirgDo42KkLNxANoFTOzLqnbe1qKdW1E); one way to have an opt-in approach would be to make the bot account restricted, which will prevent it from automatically having read access to public repos. This means that the list of repos the bot is checking will be limited to only those that have explicitly given renovate read permissions (either at the org level or the repo level). I expect this to significantly reduce the load on the infra hosting renovate, since it would no longer be checking the files of basically every repo on CB, and possibly the receiving end too (Codeberg API). Regarding Otto's comment here https://codeberg.org/Codeberg/Community/issues/799#issuecomment-689122, > I recall that Renovate wasn't very efficient? From anecdotal experience running it on my personal forgejo instance, this feels... unfortunately very much like the case. It varies wildly based on repo-specific config; sometimes operating on 7-8 repos will take upwards of 10 minutes (serially) if, for example, `dependencyDashboardOSVVulnerabilitySummary` is enabled. In that particular case, I also had to bump the memory limit of that job up to 1Gi - 1Gi of RAM per 8 repos is... not very scalable even _if_ this is the worst case scenario. If 8 hours somehow isn't enough to process the whole of CB, we could possibly consider somehow dividing up the namespace and parallelising. That said, I'm more concerned about RAM or (possibly) disk usage, depending on how the cache is structured; I want to observe renovate's behaviour some more before even trying to estimate limits :/

@pat-s I notice that both you and @6543, who made Codeberg-Infrastructure/configuration-as-code#29 are listed as maintainers of @renovate-bot - is that related to this proposal?

@pat-s I notice that both you and @6543, who made https://codeberg.org/Codeberg-Infrastructure/configuration-as-code/pulls/29 are listed as maintainers of [@renovate-bot](https://codeberg.org/renovate-bot) - is that related to this proposal?

@jthvai He just reserved the user name. If you want to help with the bot and @pat-s agrees we can give you access to the account.

@jthvai He just reserved the user name. If you want to help with the bot and @pat-s agrees we can give you access to the account.
Author
Member
Copy link

@fnetX No container is needed. Renovate is not a standalone application but just needs to be invoked. This would happen using Woodpecker anyhow. What would be needed infrastructure-wise is a Redis instance (if there isn't one yet, this could be indeed a separate container then) and a remote storage for the repo cache (S3 usually).

one way to have an opt-in approach would be to make the bot account restricted, which will prevent it from automatically having read access to public repos. This means that the list of repos the bot is checking will be limited to only those that have explicitly given renovate read permissions (either at the org level or the repo level).

That is what I proposed in the OP already, yes.

Resources: This shouldn't be an issue, CI has enough memory. With repo and dependency caching enabled, renovate is quite ok I'd say for what it provides.

If 8 hours somehow isn't enough to process the whole of CB, we could possibly consider somehow dividing up the namespace and parallelising.

Well, I didn't expect to come anywhere close to that number. I didn't choose an interval of 8 hours in the hope renovate has finished by then. I chose/proposed it as a middle ground between automation and resource usage overall. Having three runs per day should suffice for any project.

@pat-s I notice that both you and @6543, who made Codeberg-Infrastructure/configuration-as-code#29 are listed as maintainers of @renovate-bot - is that related to this proposal?

Yes, the bot already runs for selected CB-internal repos of internal, see

"autodiscoverFilter": [
"Codeberg-Infrastructure/renovate-config",
"Codeberg-Infrastructure/configuration-as-code",
"Codeberg/pages-server",
"Codeberg-CI/examples"
],

.
Currently, the runs are done without caching as only a few repos are checked, but this should be changed for a "proper" solution.
I initiated all the renovate stuff so far. I also did so in WP and Gitea and both projects profit greatly from renovate overall so far. I am not affiliated with renovate, I just think it is a great & helpful project.

@fnetX No container is needed. Renovate is not a standalone application but just needs to be invoked. This would happen using Woodpecker anyhow. What would be needed infrastructure-wise is a Redis instance (if there isn't one yet, this could be indeed a separate container then) and a remote storage for the repo cache (S3 usually). > one way to have an opt-in approach would be to make the bot account restricted, which will prevent it from automatically having read access to public repos. This means that the list of repos the bot is checking will be limited to only those that have explicitly given renovate read permissions (either at the org level or the repo level). That is what I proposed in the OP already, yes. Resources: This shouldn't be an issue, CI has enough memory. With repo and dependency caching enabled, `renovate` is quite ok I'd say for what it provides. > If 8 hours somehow isn't enough to process the whole of CB, we could possibly consider somehow dividing up the namespace and parallelising. Well, I didn't expect to come anywhere close to that number. I didn't choose an interval of 8 hours in the hope renovate has finished by then. I chose/proposed it as a middle ground between automation and resource usage overall. Having three runs per day should suffice for any project. > @pat-s I notice that both you and @6543, who made Codeberg-Infrastructure/configuration-as-code#29 are listed as maintainers of @renovate-bot - is that related to this proposal? Yes, the bot already runs for selected CB-internal repos of internal, see https://codeberg.org/Codeberg-Infrastructure/renovate-config/src/commit/c4942e044fd67c82e573fb1610fa2a5d65f239e7/default.json#L12-L17. Currently, the runs are done without caching as only a few repos are checked, but this should be changed for a "proper" solution. I initiated all the renovate stuff so far. I also did so in WP and Gitea and both projects profit greatly from `renovate` overall so far. I am not affiliated with renovate, I just think it is a great & helpful project.

Hi, I'm one of the maintainer of the renovate bot.

I think Forgejo needs some security improvements before you can run one instance on all repos.
A malcious user could otherwise gain access the all repos with a crafted repo.
We can't garantee that code from repo get's excecuted.
We're trying to avoid this under all circumstances by default but you never know what package managers are doing when called by renovate.

So my suggestion is to somehow get limited api keys, so they can be soped to orgs / repos before running renovate on unstrusted repos.

When there is something like that, then i can try to priorize to get forgejo1 support to the mend renovate community edition2 .
That's a stateful renovate variant with job queue and states. It can use repo hooks to have instant runs like the hosted app on github.

Hi, I'm one of the maintainer of the renovate bot. I think Forgejo needs some security improvements before you can run one instance on all repos. A malcious user could otherwise gain access the all repos with a crafted repo. We can't garantee that code from repo get's excecuted. We're trying to avoid this under all circumstances by default but you never know what package managers are doing when called by renovate. So my suggestion is to somehow get limited api keys, so they can be soped to orgs / repos before running renovate on unstrusted repos. When there is something like that, then i can try to priorize to get forgejo[^2] support to the mend renovate community edition[^1]. That's a stateful renovate variant with job queue and states. It can use repo hooks to have instant runs like the hosted app on github. [^1]: https://github.com/mend/renovate-ce-ee [^2]: https://github.com/mend/renovate-ce-ee/issues/293

Thank you very much for your input @viceice, that's very good to know. 😨

A malcious user could otherwise gain access the all repos with a crafted repo.

Are package managers run with the same environment variables as renovate itself (i.e. do package managers have access to the RENOVATE_TOKEN env var)?

limited api keys, so they can be scoped to orgs / repos before running renovate on unstrusted repos

If the concern is executing unknown code (in the process of using package managers), would you be willing to explain how scoped API keys could remediate the situation? Are you envisioning renovate being given (only) a separate key for each org/repo per run, such that the damage would be only limited to the scope of that key?

Thank you very much for your input @viceice, that's very good to know. 😨 > A malcious user could otherwise gain access the all repos with a crafted repo. Are package managers run with the same environment variables as renovate itself (i.e. do package managers have access to the `RENOVATE_TOKEN` env var)? > limited api keys, so they can be scoped to orgs / repos before running renovate on unstrusted repos If the concern is executing unknown code (in the process of using package managers), would you be willing to explain how scoped API keys could remediate the situation? Are you envisioning renovate being given (only) a separate key for each org/repo per run, such that the damage would be only limited to the scope of that key?

What would be needed infrastructure-wise is a Redis instance (if there isn't one yet, this could be indeed a separate container then)

There's not really a way to namespace applications at the admin level for redis, as it was designed for each application to have its own redis instance - this probably should be a separate container either way. I'd be happy to cook up a config for lxc or something, but I feel like we should consider viceice's points first.

remote storage for the repo cache (S3 usually)

I feel like I vaguely remember that CB is already using object storage somewhere already? I'm not sure where I got that from, and I can't seem to find it anymore

> What would be needed infrastructure-wise is a Redis instance (if there isn't one yet, this could be indeed a separate container then) There's not really a way to namespace applications at the admin level for redis, as it was designed for each application to have its own redis instance - this probably should be a separate container either way. I'd be happy to cook up a config for lxc or something, but I feel like we should consider viceice's points first. > remote storage for the repo cache (S3 usually) I feel like I vaguely remember that CB is already using object storage somewhere already? I'm not sure where I got that from, and I can't seem to find it anymore

When there is something like that, then i can try to priorize to get forgejo support to the mend renovate community edition.
That's a stateful renovate variant with job queue and states. It can use repo hooks to have instant runs like the hosted app on github.

As lovely as that sounds, Codeberg would probably not be able to use renovate CE since it's closed source. I haven't found anything official explicitly prohibiting the use of closed source projects in CB's infra, but it's kind of implied by "Powered by Free Software!", on the front page.

> When there is something like that, then i can try to priorize to get forgejo support to the mend renovate community edition. That's a stateful renovate variant with job queue and states. It can use repo hooks to have instant runs like the hosted app on github. As lovely as that sounds, Codeberg would probably not be able to use renovate CE since it's closed source. I haven't found anything official explicitly prohibiting the use of closed source projects in CB's infra, but it's kind of implied by "Powered by Free Software!", on the front page.

@jthvai

Correct, Codeberg has been started with the promise of only using free software. And as long as I am on board that won't change.

@jthvai Correct, Codeberg has been started with the promise of only using free software. And as long as I am on board that won't change.

Thank you very much for your input @viceice, that's very good to know. 😨

A malcious user could otherwise gain access the all repos with a crafted repo.

Are package managers run with the same environment variables as renovate itself (i.e. do package managers have access to the RENOVATE_TOKEN env var)?

Not full env by default. but the token is internally added to a simple host rule, so if we need to execute a package manager like npm or yarn, we pass auth details to that manager, so it would be able to access private registries.
so if someone can craft the package manager somehow, then it will be able to read the token.

so if renovate find a .npmrc like

@scope:registry=https://codeberg.org/api/packages/some-org/npm/

then renovate will search all known host rules for a matching one and add it as token or password to the .npmrc before calling the manager to update the lockfile.

This is nearly same for any manager which has some kind of lockfiles where we need to call an external tool.

limited api keys, so they can be scoped to orgs / repos before running renovate on unstrusted repos

If the concern is executing unknown code (in the process of using package managers), would you be willing to explain how scoped API keys could remediate the situation? Are you envisioning renovate being given (only) a separate key for each org/repo per run, such that the damage would be only limited to the scope of that key?

Yes, the token should only have write access to the repo it works on and can have read public repos.
The renovate app for github also adds read private repos on same org when the target repo is private.

Correct, Codeberg has been started with the promise of only using free software. And as long as I am on board that won't change.

No problem, the open source renovate cli will do it too

> Thank you very much for your input @viceice, that's very good to know. 😨 > > > A malcious user could otherwise gain access the all repos with a crafted repo. > > Are package managers run with the same environment variables as renovate itself (i.e. do package managers have access to the `RENOVATE_TOKEN` env var)? Not full env by default. but the token is internally added to a simple host rule, so if we need to execute a package manager like npm or yarn, we pass auth details to that manager, so it would be able to access private registries. so if someone can craft the package manager somehow, then it will be able to read the token. so if renovate find a `.npmrc` like ```ini @scope:registry=https://codeberg.org/api/packages/some-org/npm/ ``` then renovate will search all known host rules for a matching one and add it as token or password to the `.npmrc` before calling the manager to update the lockfile. This is nearly same for any manager which has some kind of lockfiles where we need to call an external tool. > > limited api keys, so they can be scoped to orgs / repos before running renovate on unstrusted repos > > If the concern is executing unknown code (in the process of using package managers), would you be willing to explain how scoped API keys could remediate the situation? Are you envisioning renovate being given (only) a separate key for each org/repo per run, such that the damage would be only limited to the scope of that key? Yes, the token should only have write access to the repo it works on and can have read public repos. The renovate app for github also adds read private repos on same org when the target repo is private. > Correct, Codeberg has been started with the promise of only using free software. And as long as I am on board that won't change. No problem, the open source renovate cli will do it too
Author
Member
Copy link

@viceice
Can you explain what is in detail different between GH and Codeberg WRT to execution? In the end, a hosted app would also "just" run renovate. And this version needs access to the repos and users can opt-in on their own. So I don't understand yet in which detail the execution on CB would be a security risk.

If so, then any execution on CB would be a security risk as one could create a repo which gains access to other repos to which the bot has access to. And if so, why would this only be possible on CB/Forgejo?

@viceice Can you explain what is *in detail* different between GH and Codeberg WRT to execution? In the end, a hosted app would also "just" run renovate. And this version needs access to the repos and users can opt-in on their own. So I don't understand yet in which detail the execution on CB would be a security risk. If so, then any execution on CB would be a security risk as one could create a repo which gains access to other repos to which the bot has access to. And if so, why would this only be possible on CB/Forgejo?
Author
Member
Copy link

There's not really a way to namespace applications at the admin level for redis, as it was designed for each application to have its own redis instance - this probably should be a separate container either way. I'd be happy to cook up a config for lxc or something, but I feel like we should consider viceice's points first.

There's no issue bundling multiple applications in a single redis or redis-cluster instance. I don't think a separate LXC container is needed for every app which needs "a bit' of redis.

> There's not really a way to namespace applications at the admin level for redis, as it was designed for each application to have its own redis instance - this probably should be a separate container either way. I'd be happy to cook up a config for lxc or something, but I feel like we should consider viceice's points first. There's no issue bundling multiple applications in a single redis or redis-cluster instance. I don't think a separate LXC container is needed for every app which needs "a bit' of redis.

Can you explain what is in detail different between GH and Codeberg WRT to execution? In the end, a hosted app would also "just" run renovate.

The implication appears to be that for each repository the GH App (renovate) is installed, it gets/has a separate repo- or org-scoped token.

This currently cannot be the case on CB as forgejo doesn't support repo- or org-scoped API tokens, only permission restrictions at the user level. In order to create comparable security boundaries, the bot would need to run as a separate user per repo (which is not practical).

See also the GH docs on apps, particularly:

When you install an app, you will also choose which repositories to grant the GitHub App access to.

> Can you explain what is in detail different between GH and Codeberg WRT to execution? In the end, a hosted app would also "just" run renovate. The implication appears to be that for each repository the GH App (renovate) is installed, it gets/has a separate repo- or org-scoped token. This currently cannot be the case on CB as forgejo doesn't support repo- or org-scoped API tokens, only permission restrictions at the user level. In order to create comparable security boundaries, the bot would need to run as a _separate user_ per repo (which is not practical). See also the [GH docs on apps](https://docs.github.com/en/apps/using-github-apps/installing-a-github-app-from-a-third-party), particularly: > When you install an app, you will also choose which repositories to grant the GitHub App access to.
Author
Member
Copy link

@jthvai Thanks.

Overall, I still think that the mentioned points are not a blocker. The possible security threat should be prominently mentioned in the description of the service.
Users which are afraid do not need to opt-in.
Most users host FOSS software in public repos/orgs and do probably not care too much if somebody would really have such strong motivation to get access to the code or private registries.
There is always and still the alternative to host your own renovate bot for more privacy.

In the end, there are all sorts of possible external access, starting alone by service admins of the CI being able to possibly inspect all logs. Again, CB is a platform for FOSS and (mainly) public repos. For full privacy and security, self-hosting is needed anyhow.

A hosted renovate-ce bot would certainly be great, but I think this won't happen so quickly.

@jthvai Thanks. Overall, I still think that the mentioned points are not a blocker. The *possible* security threat should be prominently mentioned in the description of the service. Users which are afraid do not need to opt-in. Most users host FOSS software in public repos/orgs and do probably not care too much if somebody would really have such strong motivation to get access to the code or private registries. There is always and still the alternative to host your own renovate bot for more privacy. In the end, there are all sorts of possible external access, starting alone by service admins of the CI being able to possibly inspect all logs. Again, CB is a platform for FOSS and (mainly) public repos. For full privacy and security, self-hosting is needed anyhow. A hosted renovate-ce bot would certainly be great, but I think this won't happen so quickly.

probably not care too much if somebody would really have such strong motivation to get access to the code or private registries.

The main issue is that the token would be granting write access to all of these repos1 - so privacy is not the chief concern, the integrity of the codebase is.

In addition to mentioning the threat in the description, we could suggest protecting important branches as a mitigation.

I don't claim to have a PoC, but if it is significant enough that a renovate dev came over to personally warn us to be careful...


Edit:

all sorts of possible external access, starting alone by service admins of the CI being able to possibly inspect all logs

The user deliberately and voluntarily consents to the admins of the CI having access to their repository, and generally may trust that the admin will not give that access to a third party without notifying the user first.

In the event of token compromise (as discussed here), the user generally has not consented to another user of the service, not the admin of the bot, having access to their repository.

I don't really agree that these situations are comparable. While technically the admin is "no longer liable" if the possibility of compromise is noted, and while technically this is included in the "this service is provided as is etc.", I personally would make an additional note if I was operating a service where lateral movement is plausible with standard user access to the service.


  1. given renovate creates PR branches in the repo itself, it cannot function without write access ↩︎

> probably not care too much if somebody would really have such strong motivation to get access to the code or private registries. The main issue is that the token would be granting _write_ access to all of these repos[^1] - so privacy is not the chief concern, the integrity of the codebase is. In addition to mentioning the threat in the description, we could suggest [protecting important branches](https://forgejo.org/docs/latest/user/protection/) as a mitigation. I don't claim to have a PoC, but if it is significant enough that a renovate dev came over to personally warn us to be careful... *** Edit: > all sorts of possible external access, starting alone by service admins of the CI being able to possibly inspect all logs The user deliberately and voluntarily consents to the admins of the CI having access to their repository, and generally may trust that the admin will not give that access to a third party without notifying the user first. In the event of token compromise (as discussed here), the user generally has not consented to _another user of the service_, not the admin of the bot, having access to their repository. I don't really agree that these situations are comparable. While technically the admin is "no longer liable" if the possibility of compromise is noted, and while technically this is included in the "this service is provided as is _etc._", I _personally_ would make an additional note if I was operating a service where lateral movement is plausible with standard user access to the service. [^1]: given renovate creates PR branches in the repo itself, it cannot function without write access

yes, renovate needs write access to each processing repo. so a malicious user can manipulate other Foss software within the context of the bot.

you can of cause protect important branches, but you loose automerge feature then.

the bot also needs write access to issues.

so for now I would strongly discourage to use one user for all. you should at least use one user per organization until token can be more scoped.

I would also suggest that an admin should approve the opt-in.

since Forgejo becomes a hard fork, can't we now prioritize scoped token? or pay someone to implement it?

yes, renovate needs write access to each processing repo. so a malicious user can manipulate other Foss software within the context of the bot. you can of cause protect important branches, but you loose automerge feature then. the bot also needs write access to issues. so for now I would strongly discourage to use one user for all. you should at least use one user per organization until token can be more scoped. I would also suggest that an admin should approve the opt-in. since Forgejo becomes a hard fork, can't we now prioritize scoped token? or pay someone to implement it?
Author
Member
Copy link

Alright, then close this one here until org-scoped tokens are available. Thanks everyone for the discussion and feedback!

Alright, then close this one here until org-scoped tokens are available. Thanks everyone for the discussion and feedback!
Sign in to join this conversation.
No Branch/Tag specified
wiki-notice
main
No results found.
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
6 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Codeberg/Contributing#47
Reference in a new issue
Codeberg/Contributing
No description provided.
Delete branch "%!s()"

Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?