1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-10-18 20:09:08 +02:00
Commit Graph

9294 Commits

Author SHA1 Message Date
Fredrik Strand Oseberg
f34d187cd9
Refactor/separate client and admin store (#5006)
This PR is the first step in separating the client and admin stores.
Currently our feature toggle services uses the client store to serve
multiple purposes. 

Admin API uses the feature toggle service to serve both the feature
toggle list and playground features, while the client API uses the
feature toggle service to serve client features. The admin API can
change often and have very different requirements than the client API,
which changes infrequently and generally keeps the same stable structure
for long periods of time. This architecture is error prone, because when
you need to make changes to the admin API, you can very easily affect
the client API.

I aim to put up a stone wall between the two APIs. Complete separation
between the two APIs, at the cost of some duplication.

In this PR I have created a feature oriented architecture for client
features and disconnected the client API from the feature toggle
service. It now goes through it's own service to it's own store. For
feature toggle service I have duplicated and replaced the functionality
that serves /api/admin/features, I have kept a lot of the ugliness in
the code and haven't removed anything in order to avoid breaking
changes.

Next steps: 
* Move playground to admin API
* Remove client-feature-toggle-store from feature-toggle-service
2023-10-12 13:58:23 +02:00
Jaanus Sellin
7b7a2a706c
fix: enable segment importing for oss (#5010) 2023-10-12 13:43:43 +03:00
Nuno Góis
66304cf8e7
feat: message banners table migration (#5009)
https://linear.app/unleash/issue/2-1485/db-create-migration-for-a-new-internal-message-banners-table

Adds a DB migration for a new `message_banners` table.
2023-10-12 11:27:00 +01:00
Nuno Góis
2ab2aa1f6d
feat: dynamic icons by adding material symbols font (#5008)
https://linear.app/unleash/issue/2-1502/add-support-for-custom-dynamic-icons-mui-icon-component

Adds support for custom dynamic icons by adding the [Material Symbols
Outlined font](https://fonts.google.com/icons) and setting the MUI Icon
component base class. See:
https://mui.com/material-ui/icons/#icon-font-icons

Message banner use case: This will not only enable us to set custom
icons for external message banners, but will also let users configure
their desired icon from the set of options in the font.
2023-10-12 11:22:23 +01:00
Jaanus Sellin
2059706e77
feat: export dependent feature toggles (#5007) 2023-10-12 12:56:10 +03:00
Gastón Fournier
7343183f2d
chore: split interfaces for import and export (#5004)
## About the changes
This splits the interfaces for import and export, especially because the
import functionality has to be replaced in enterprise repo.

This is a breaking change because of the service renames, but I'll have
the PR for the other repository ready so we reduce the time to fix. I
intentionally avoided doing it backward compatible because of time.
2023-10-12 11:34:09 +02:00
Mateusz Kwasniewski
cfcf9de65a
feat: Protect archive feature (#5003) 2023-10-12 08:38:03 +02:00
Mark Fulton
2754c26f2e
docs/video embed, academy video embed fixes (#5005)
PR contains the following:

1) New video embeds for the following docs:

- website/docs/reference/deploy/environment-import-export.mdx
- website/docs/reference/playground.mdx
- website/docs/reference/strategy-constraints.md
- website/docs/topics/a-b-testing.md

2) Improvements to the Academy course playlist embedding for the three
Academy courses. Tested the standard method of embedding video, and it
seems this works well for playlists too.
Switching to the native Docusaurus embed solves the issue with dynamic
resizing. Rather than a static embed size the video will now scale to
the browser window size.
2023-10-11 14:20:16 -05:00
Mateusz Kwasniewski
30e9fb87e9
feat: prevent adding dependency to archived or removed parent (#4987) 2023-10-11 16:21:57 +02:00
Mark Fulton
7ea7c08654
Docs/academy video player (#5002)
Added explanative text to three courses on embedded playlist video
player usage
2023-10-11 13:22:56 +00:00
Nuno Góis
742abab41e
feat: multiple external message banners (#4998)
https://linear.app/unleash/issue/2-1495/adapt-existing-message-banner-component-to-be-more-reusablegeneric

https://linear.app/unleash/issue/2-1496/add-support-for-multiple-external-message-banners

This PR does 2 things:
- Refactors the `MessageBanner` component to be more generic and
reusable, by accepting the message info through props;
 - Adds support for multiple external message banners;
2023-10-11 13:42:05 +01:00
Nuno Góis
7d9698fffa
fix: missing uiFlag newInviteLink (#5000)
Adds a missing uiFlag: `newInviteLink`
2023-10-11 12:10:08 +00:00
Nuno Góis
c3575c7727
refactor: make uiFlags typesafe (#4996)
This should add some typesafety to our usage of uiFlags.
2023-10-11 12:44:54 +01:00
andreas-unleash
4e8c0478bf
fix: export NotFoundError and ISegmentService in internals.ts (#4997)
export NotFoundError and ISegmentService in internals.ts

Signed-off-by: andreas-unleash <andreas@getunleash.ai>
2023-10-11 14:31:45 +03:00
Jaanus Sellin
69286339fc
feat: make invite link more visible (#4984) 2023-10-11 14:31:32 +03:00
Nuno Góis
65f424156c
feat: re-order message banners (#4995)
https://linear.app/unleash/issue/2-1494/re-order-message-banners

- Re-orders message banners to fit into this logic:

>1. Maintenance banner
>2. External message banner(s) - Most likely coming from Unleash
>3. Internal message banner(s)

- Renames the feature flag to better reflect the feature behavior;
- Lays a basic skeleton structure for this new feature;
2023-10-11 11:55:54 +01:00
Fredrik Strand Oseberg
bc96216daa
Refactor/move features to feature oriented architecture (#4994)
This PR gathers feature related files in the same folder.
2023-10-11 09:38:57 +02:00
Mark Fulton
a3b4e9db5f
docs: updated sidebars and added missing doc ID (#4993)
Updated `sidebars.js` to incorporate `Getting Started` as top level doc,
with Unleash Academy in child structure (order as discussed with
@dgorton ). See screenshot.

Also added missing `id` to `getting-started.md`


![image](https://github.com/Unleash/unleash/assets/128738155/52881918-a38b-4e6a-b6c8-bbeb1cd0a232)
2023-10-10 16:18:59 -05:00
Mark Fulton
053a4637e1
initial docs for Unleash Academy (#4992)
Set of four docs for Unleash Academy, with overview page and three
course pages. Navigation to be updated separately.
2023-10-10 15:05:13 -05:00
Sebastian Bury
9a62f6a64f
create getting-started and remove quickstart (#4991)
<!-- Thanks for creating a PR! To make it easier for reviewers and
everyone else to understand what your changes relate to, please add some
relevant content to the headings below. Feel free to ignore or delete
sections that you don't think are relevant. Thank you! ❤️ -->

## About the changes
<!-- Describe the changes introduced. What are they and why are they
being introduced? Feel free to also add screenshots or steps to view the
changes if they're visual. -->

<!-- Does it close an issue? Multiple? -->
Closes #

<!-- (For internal contributors): Does it relate to an issue on public
roadmap? -->
<!--
Relates to [roadmap](https://github.com/orgs/Unleash/projects/10) item:
#
-->

### Important files
<!-- PRs can contain a lot of changes, but not all changes are equally
important. Where should a reviewer start looking to get an overview of
the changes? Are any files particularly important? -->


## Discussion points
<!-- Anything about the PR you'd like to discuss before it gets merged?
Got any questions or doubts? -->

---------

Co-authored-by: Drew Gorton <dgorton@users.noreply.github.com>
Co-authored-by: Mark Fulton <128738155+markunl@users.noreply.github.com>
2023-10-10 15:03:17 -05:00
Nuno Góis
2222c47d10
feat: add internalMessageBanner feature flag (#4990)
https://linear.app/unleash/issue/2-1487/feature-flag-add-a-new-internalmessagebanner-feature-flag-for-this

Adds a new `internalMessageBanner` feature flag.
2023-10-10 20:03:59 +01:00
Nuno Góis
b0eba109d3
docs: add feature availability troubleshooting guide (#4989)
Adds a small troubleshooting guide for Unleash features availability.
This is not specific to features that have a visual component in the
admin UI, but that's the most common scenario.
2023-10-10 11:17:06 -05:00
Thomas Heartman
4bc9908287
docs: add a custom_edit_url for sdks and edge/proxy (#4985)
This change adds custom edit urls for all the external readmes (sdks,
edge, proxy) that we put in the docs. This makes it so that following
the "edit this document" link takes you to the correct location, instead
of to a file that doesn't exist in the main Unleash repo.

Important caveat: this will only work for repos where the readme is
called `README.md` (capitalization matters). Currently, this is all our
repos, but it's something to be aware of for later.

We don't currently record what the readme files are called directly in
the docs, so to know that for sure, we'd have to build an extra
integration to check and fix that automatically. It may be worth doing
in the future, but for now, I think it's fine. We could also just rename
the readme files if we find any issues.
2023-10-10 11:11:54 -05:00
Gastón Fournier
b802ced0f5
chore: avoid building frontend if not needed (#4982)
## About the changes
Looks like we're building twice:
https://github.com/Unleash/unleash/actions/runs/6468079228/job/17559391393#step:5:136
2023-10-10 15:35:11 +02:00
dependabot[bot]
cc4dbe8c92
chore(deps): bump postcss from 8.4.21 to 8.4.31 in /frontend (#4919) 2023-10-10 14:44:46 +02:00
Fredrik Strand Oseberg
a2ca7b0d35
Refactor/last seen at read feature overview (#4986)
Refactor feature overview to use the last seen store
2023-10-10 14:40:36 +02:00
Mateusz Kwasniewski
2f84ac88e6
feat: delete dependnecy button through change request (#4983) 2023-10-10 14:38:10 +02:00
Christopher Kolstad
0c069b1385
fix: added await to getActiveUsers tests 2023-10-10 13:23:20 +02:00
Christopher Kolstad
1edd73db45
feat: feature changes counted in new table (#4958)
As part of more telemetry on the usage of Unleash. 

This PR adds a new `stat_` prefixed table as well as a trigger on the
events table trigger on each insert to increment a counter per
environment per day.

The trigger will trigger on every insert into the events base, but will
filter and only increment the counter for events that actually have the
environment set. (there are events, like user-created, that does not
relate to a specific environment).

Bit wary on this, but since we truncate down to row per (day,
environment) combo, finding conflict and incrementing shouldn't take too
long here.

@ivarconr was it something like this you were considering?
2023-10-10 12:32:23 +02:00
Thomas Heartman
fa4d6b211a
docs: make videos bigger (#4980)
This PR changes the `VideoContent` component to:
- remove the extra text; keeps only videos
- makes videos take up the full article width
- multiple videos stack vertically (this may or may not be the best way
to handle it, but we don't have any instances of using multiple videos
as of right now, so we shouldn't touch this until we do).

By chance, it also removes a lot of trailing whitespace in files. I
suggest checking out the diff with whitespace hidden.

Before (single video):

![image](https://github.com/Unleash/unleash/assets/17786332/e47e8827-93e9-4dbc-bdfb-cdb1665fae98)


Before (if there were multiple videos): 

![image](https://github.com/Unleash/unleash/assets/17786332/f41ab11f-649f-4369-96fe-70a5d66ced40)


After (single video):

![image](https://github.com/Unleash/unleash/assets/17786332/0df9d3fd-3935-4567-93d0-470682fe4bb3)


After (if there are multiple videos): 

![image](https://github.com/Unleash/unleash/assets/17786332/98b4a590-c03c-40a1-880f-93ad05090c5e)
2023-10-10 11:42:25 +02:00
Mateusz Kwasniewski
13c794e3f2
feat: generate declaration map (#4981) 2023-10-10 11:42:08 +02:00
Fredrik Strand Oseberg
c97bcc65e6
Refactor/project overview last seen at test (#4979)
Increase test coverage of last seen in project overview
2023-10-10 10:43:45 +02:00
Mateusz Kwasniewski
af50fc2fd3
feat: visualize dependencies managment in change requests (#4978) 2023-10-10 10:36:13 +02:00
Mateusz Kwasniewski
b4c8f92a26
feat: do not allow to manage dependencies directly with cr enabled (#4971) 2023-10-10 09:25:03 +02:00
Fredrik Strand Oseberg
30d8444c80
fix: refactor getProjectOverview store method (#4972)
This PR cleans up and refactors the feature-strategy-store method
getFeatureOverview to join on the new table and attempts to make the
function more readable by extracting some of the logic into separate
functions. Keeping the LastSeenMapper for now in case there is a reason
to use it for the other endpoints.
2023-10-10 07:34:21 +02:00
Mateusz Kwasniewski
ab739eb6c3
feat: Change request dependency UI (#4966) 2023-10-09 14:06:00 +02:00
Gastón Fournier
7f61438095
chore: Rename validate step (#4969)
This is to bypass branch protection rules
2023-10-09 13:55:38 +02:00
Simon Hornby
4c22287a21
docs: rollback docusaurus upgrade so the docs work (#4965) 2023-10-09 11:57:05 +02:00
Mateusz Kwasniewski
6b29b6c317
feat: orval types with change request for dependencies (#4961) 2023-10-09 11:52:41 +02:00
Fredrik Strand Oseberg
d896dbd0c7
Fix/last seen at by environment (#4939)
Initial architecture for last seen at by environment.
2023-10-09 10:54:00 +02:00
Gastón Fournier
34fc17146e
chore: improve type on import service (#4962)
## About the changes
Limit import type to what matters
2023-10-09 10:45:19 +02:00
David Leek
e065e2a455
feat: render segments changes in feature strategy update event messages (#4950)
## About the changes

Segment changes in predata and data columns were both showing the new
segments list

Adds formatting of what's changed with segments to feature strategy
update events, so when a user changes the strategy from using
constraints, to using segments instead, it's communicated in event
updates

results in: 

admin updated
[sample-toggle](http://localhost/projects/default/features/sample-toggle)
in project [default](http://localhost/projects/default) by updating
strategy Sample Strategy in development constraints from [userId is one
of (1,2,3)] to empty set of constraints; segments from empty set of
segments to (1)


Closes #
#4912 

### Important files

- `src/lib/services/feature-toggle-service.ts` - Segment changes in
preData and data
- `src/lib/addons/feature-event-formatter-md.ts` - Formatting segments

## Discussion points

This is an SR least effort PR - we should plan a task where we look at
how to render this list of segments in a more comprehensible way (it's
just rendering ids now)
2023-10-09 09:11:39 +02:00
Nuno Góis
e0faa3e842
fix: typo in enabled event (#4960)
Fixes a typo where we would send `disabled` for `enabled` events.


https://unleash-community.slack.com/archives/C03GWTN7XMG/p1696631381409369
2023-10-08 19:22:12 +02:00
Gastón Fournier
4fc7df84b9
fix: ignore errors on changelog generation and include token (#4926)
This backports changes made in 5.5
2023-10-06 16:39:34 +02:00
Gastón Fournier
c3e8d743bc
chore: Improve UI Config type (#4959)
Fix link types
2023-10-06 16:31:39 +02:00
Mateusz Kwasniewski
8b0cf8b11d
feat: allow to delete dependencies when no orphans (#4952) 2023-10-06 13:39:16 +02:00
Gastón Fournier
52fa872fe6
chore: handle transactions already started at the controller layer (#4953)
## About the changes
This PR adds a method to safeguard us from opening a new transaction
while inside another transaction, resulting in two isolated transactions
that will not be atomic (if one fails, the other might still complete
successfully).


bbbe4d4637/lib/knex-builder/make-knex.js (L143C5-L144C88)

We're currently opening transactions at the controller layer 

2746bd1517/src/lib/features/export-import-toggles/export-import-controller.ts (L206-L208)

but in some other places, we do it at the store level:

2746bd1517/src/lib/db/access-store.ts (L577)


## Alternative
We can remove store-level transactions and move them to the controller
following this approach:


cb034976b9/src/lib/services/index.ts (L282-L284)


cb034976b9/src/lib/features/export-import-toggles/export-import-controller.ts (L206-L208)

This option is more expensive because we have to:
1. Write the factory methods that propagate the transaction to the
stores (therefore creating the store factory methods as well)
2. Identify the methods for creating the transactions at the store level
and backtrack the calls until the controller layer
2023-10-06 13:38:32 +02:00
renovate[bot]
2746bd1517
chore(deps): update dependency @babel/core to v7.23.0 (#4955)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@babel/core](https://babel.dev/docs/en/next/babel-core)
([source](https://togithub.com/babel/babel)) | [`7.22.20` ->
`7.23.0`](https://renovatebot.com/diffs/npm/@babel%2fcore/7.22.20/7.23.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@babel%2fcore/7.23.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@babel%2fcore/7.23.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@babel%2fcore/7.22.20/7.23.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@babel%2fcore/7.22.20/7.23.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>babel/babel (@&#8203;babel/core)</summary>

###
[`v7.23.0`](https://togithub.com/babel/babel/blob/HEAD/CHANGELOG.md#v7230-2023-09-25)

[Compare
Source](https://togithub.com/babel/babel/compare/v7.22.20...v7.23.0)

##### 🚀 New Feature

- `babel-plugin-proposal-import-wasm-source`,
`babel-plugin-syntax-import-source`,
`babel-plugin-transform-dynamic-import`
- [#&#8203;15870](https://togithub.com/babel/babel/pull/15870) Support
transforming `import source` for wasm
([@&#8203;nicolo-ribaudo](https://togithub.com/nicolo-ribaudo))
- `babel-helper-module-transforms`, `babel-helpers`,
`babel-plugin-proposal-import-defer`,
`babel-plugin-syntax-import-defer`,
`babel-plugin-transform-modules-commonjs`, `babel-runtime-corejs2`,
`babel-runtime-corejs3`, `babel-runtime`, `babel-standalone`
- [#&#8203;15878](https://togithub.com/babel/babel/pull/15878) Implement
`import defer` proposal transform support
([@&#8203;nicolo-ribaudo](https://togithub.com/nicolo-ribaudo))
-   `babel-generator`, `babel-parser`, `babel-types`
- [#&#8203;15845](https://togithub.com/babel/babel/pull/15845) Implement
`import defer` parsing support
([@&#8203;nicolo-ribaudo](https://togithub.com/nicolo-ribaudo))
- [#&#8203;15829](https://togithub.com/babel/babel/pull/15829) Add
parsing support for the "source phase imports" proposal
([@&#8203;nicolo-ribaudo](https://togithub.com/nicolo-ribaudo))
- `babel-generator`, `babel-helper-module-transforms`, `babel-parser`,
`babel-plugin-transform-dynamic-import`,
`babel-plugin-transform-modules-amd`,
`babel-plugin-transform-modules-commonjs`,
`babel-plugin-transform-modules-systemjs`, `babel-traverse`,
`babel-types`
- [#&#8203;15682](https://togithub.com/babel/babel/pull/15682) Add
`createImportExpressions` parser option
([@&#8203;JLHwung](https://togithub.com/JLHwung))
-   `babel-standalone`
- [#&#8203;15671](https://togithub.com/babel/babel/pull/15671) Pass
through nonce to the transformed script element
([@&#8203;JLHwung](https://togithub.com/JLHwung))
- `babel-helper-function-name`,
`babel-helper-member-expression-to-functions`, `babel-helpers`,
`babel-parser`, `babel-plugin-proposal-destructuring-private`,
`babel-plugin-proposal-optional-chaining-assign`,
`babel-plugin-syntax-optional-chaining-assign`,
`babel-plugin-transform-destructuring`,
`babel-plugin-transform-optional-chaining`, `babel-runtime-corejs2`,
`babel-runtime-corejs3`, `babel-runtime`, `babel-standalone`,
`babel-types`
- [#&#8203;15751](https://togithub.com/babel/babel/pull/15751) Add
support for optional chain in assignments
([@&#8203;nicolo-ribaudo](https://togithub.com/nicolo-ribaudo))
-   `babel-helpers`, `babel-plugin-proposal-decorators`
- [#&#8203;15895](https://togithub.com/babel/babel/pull/15895) Implement
the "decorator metadata" proposal
([@&#8203;nicolo-ribaudo](https://togithub.com/nicolo-ribaudo))
-   `babel-traverse`, `babel-types`
- [#&#8203;15893](https://togithub.com/babel/babel/pull/15893) Add
`t.buildUndefinedNode`
([@&#8203;liuxingbaoyu](https://togithub.com/liuxingbaoyu))
-   `babel-preset-typescript`
- [#&#8203;15913](https://togithub.com/babel/babel/pull/15913) Add
`rewriteImportExtensions` option to TS preset
([@&#8203;nicolo-ribaudo](https://togithub.com/nicolo-ribaudo))
-   `babel-parser`
- [#&#8203;15896](https://togithub.com/babel/babel/pull/15896) Allow TS
tuples to have both labeled and unlabeled elements
([@&#8203;yukukotani](https://togithub.com/yukukotani))

##### 🐛 Bug Fix

-   `babel-plugin-transform-block-scoping`
- [#&#8203;15962](https://togithub.com/babel/babel/pull/15962) fix:
`transform-block-scoping` captures the variables of the method in the
loop ([@&#8203;liuxingbaoyu](https://togithub.com/liuxingbaoyu))

##### 💅 Polish

-   `babel-traverse`
- [#&#8203;15797](https://togithub.com/babel/babel/pull/15797) Expand
evaluation of global built-ins in `@babel/traverse`
([@&#8203;lorenzoferre](https://togithub.com/lorenzoferre))
-   `babel-plugin-proposal-explicit-resource-management`
- [#&#8203;15985](https://togithub.com/babel/babel/pull/15985) Improve
source maps for blocks with `using` declarations
([@&#8203;nicolo-ribaudo](https://togithub.com/nicolo-ribaudo))

##### 🔬 Output optimization

- `babel-core`, `babel-helper-module-transforms`,
`babel-plugin-transform-async-to-generator`,
`babel-plugin-transform-classes`,
`babel-plugin-transform-dynamic-import`,
`babel-plugin-transform-function-name`,
`babel-plugin-transform-modules-amd`,
`babel-plugin-transform-modules-commonjs`,
`babel-plugin-transform-modules-umd`,
`babel-plugin-transform-parameters`,
`babel-plugin-transform-react-constant-elements`,
`babel-plugin-transform-react-inline-elements`,
`babel-plugin-transform-runtime`, `babel-plugin-transform-typescript`,
`babel-preset-env`
- [#&#8203;15984](https://togithub.com/babel/babel/pull/15984) Inline
`exports.XXX =` update in simple variable declarations
([@&#8203;nicolo-ribaudo](https://togithub.com/nicolo-ribaudo))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/Unleash/unleash).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4wLjMiLCJ1cGRhdGVkSW5WZXIiOiIzNy4wLjMiLCJ0YXJnZXRCcmFuY2giOiJtYWluIn0=-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-06 08:51:26 +00:00
Gastón Fournier
60a07ca38b
fix: Fail when format or lint is incorrect (#4956)
## About the changes
Format check was not throwing a failure when checking:
https://github.com/Unleash/unleash/actions/runs/6419038883/job/17428046648#step:6:10
2023-10-06 10:46:38 +02:00
Mateusz Kwasniewski
d61ccb1f6b
fix: local linter did not find formatting error (#4954) 2023-10-06 10:45:29 +02:00