1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-10-27 11:02:16 +01:00
Commit Graph

14434 Commits

Author SHA1 Message Date
Melinda Fekete
dcda481afe
docs: add FAQs to 11 principles page (#10701) 2025-10-08 16:26:09 +02:00
Thomas Heartman
7044cd4b1a
feat: Add batching functionality to new flags in production (#10756)
Adds the same batching functionality that was added to the
archived:created chart to the new flags in production chart.

In doing so, I've extracted the batching algorithm and the batched
tooltip title creation, as well as the ChartDataResult type (though
naming suggestions are still welcome on that front).

Locale 'ja':
<img width="1143" height="370" alt="image"
src="https://github.com/user-attachments/assets/827b41c6-0e67-46f4-8f82-4ba12e2120bb"
/>

Locale 'no':
<img width="1475" height="554" alt="image"
src="https://github.com/user-attachments/assets/6125c318-25fb-42bd-a520-44e6a7f7ece7"
/>
2025-10-08 12:40:11 +00:00
Mateusz Kwasniewski
cf018020df
chore: feature release plans flag (#10762) 2025-10-08 14:19:22 +02:00
Tymoteusz Czech
4ed138c151
Billing info updates (#10761) 2025-10-08 12:11:24 +00:00
Mateusz Kwasniewski
bb3d938f57
fix: transition condition type (#10760) 2025-10-08 12:50:05 +02:00
Mateusz Kwasniewski
f35804e55f
Improve release plan write model (#10759) 2025-10-08 12:27:32 +02:00
Fredrik Strand Oseberg
1d4f72cf81
feat: improve milestone automation UI positioning and styling (#10758) 2025-10-08 11:56:41 +02:00
Mateusz Kwasniewski
43fa239e72
feat: milestone transition condition (#10757) 2025-10-08 11:30:04 +02:00
Nuno Góis
9948e577ee
fix: clone environments (#10755)
https://linear.app/unleash/issue/2-3932/cloned-environments-enable-disabled-strategies-unexpectedly

Cloning environments didn't work as expected. This fixes a few of
issues:
 - Disabled strategies remain disabled after cloning
 - All strategy properties are cloned (including e.g. title)
 - Strategy cloning respects the selected projects
 - Release plans and their milestones are now correctly cloned
2025-10-08 09:48:40 +01:00
Fredrik Strand Oseberg
8072bc6706
feat: implement milestone progression form (#10749) 2025-10-08 10:15:08 +02:00
Mateusz Kwasniewski
f2115cc3db
feat: move release plans to feature environments (#10746) 2025-10-08 09:39:37 +02:00
Tymoteusz Czech
183d436e59
feat: invoice sections (#10744)
Currency formatting and cleaner invoice components
2025-10-08 09:15:43 +02:00
Gastón Fournier
fab5dc8725
fix: Information exposure through a stack trace (#10737)
Fix for
[https://github.com/Unleash/unleash/security/code-scanning/81](https://github.com/Unleash/unleash/security/code-scanning/81)

To prevent information exposure through stack traces, ensure that the
HTTP response sent to clients contains only sanitized, generic error
information, such as a status code and a simple message. Internal
details (including stack traces, error types, or internal error codes)
should not be sent to the client. These can be safely logged on the
server for debugging.

**The fix:**  
- Do not return the entire `finalError` object as JSON to the client, as
it may include fields like `stack` or `internalMessage`.
- Instead, return only a subset of fields that are safe to expose to the
user, in this case just `message` .
- Log the full error and any debugging details using the server-side
logger **as currently done**.


---
_Suggested fixes powered by Copilot Autofix. Review carefully before
merging._

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2025-10-07 16:41:40 +02:00
Gastón Fournier
8f2cf5386d
fix: flaky test when updated_at matches the time of query (#10752) 2025-10-07 16:03:57 +02:00
Thomas Heartman
3e10ca6611
fix: highlight is too wide when batching weeks in archived:created chart (#10751)
Makes it so that the default width calculation for the highlighter
plugin attempts to first use the number of entries in the data set for
the x axis, but falls back to using the number of categories if that is
not available. This is probably the more "correct" / "do what I mean"
approach to setting highlighter width.

Fixes an issue where the highlight would be too wide if the labels were
set to "auto" instead of "data".

The width function is only used in two places (the archived:created
graph and the network graph). Both of those work fine with the new
update.

Before:
<img width="831" height="401" alt="image"
src="https://github.com/user-attachments/assets/8487b95f-cc49-4ff6-a519-7f79e1048eed"
/>

After:
<img width="886" height="378" alt="image"
src="https://github.com/user-attachments/assets/ad2102cb-3342-4a28-aa54-6b31caa495e1"
/>
2025-10-07 14:34:06 +02:00
Gastón Fournier
6a63e27ebd
fix: get users total right at startup (#10750)
# Summary
Add optional lazy collection with TTL to our createGauge wrapper,
allowing a gauge to fetch its value on scrape and cache it for a
configurable duration. This lets us register a collect function directly
at gauge declaration without changing existing call sites or behavior.

We're experimenting with this, reason why we're only applying the
solution to `users_total` and will evaluate afterwards.

# Problem
- Some gauges should be computed on scrape (e.g., expensive or external
lookups) instead of being pushed continuously.
- Our current `createGauge` helper doesn’t make it easy to attach a
`collect` with caching. Each caller has to reimplement timing, caching,
and error handling.
- This leads to repeated costly work, inconsistent handling of unknown
values, and boilerplate.
# What changed
- `createGauge` now accepts two optional options in addition to the
usual prom-client options:
    - `fetchValue?: () => Promise<number | null>`
    - `ttlMs?: number`
- When `fetchValue` is provided:
    - We install a `collect` that fetches on scrape.
- Successful values are cached for `ttlMs` milliseconds (if `ttlMs` >
0).
    - If `ttlMs` is 0 or omitted, we fetch on every scrape.
- If `fetchValue` returns null or throws, we set `NaN` (indicates
`"unknown"`).

# Behavior details
## Caching:
- A value is “fresh” when successfully fetched within `ttlMs`.
- Only numeric successes are cached. null and errors are not cached;
we’ll refetch on the next scrape.
## Unknown values:
- null or thrown errors set the gauge to `NaN` so Prometheus won’t treat
it as zero.
## Compatibility:
- Backward compatible. Existing uses of `createGauge` are unchanged.
If a user-supplied `collect` exists, it still runs after the TTL logic
(can overwrite the value by design).
- API remains the same for the returned wrapper: `{ gauge, labels,
reset, set }`.
2025-10-07 14:22:33 +02:00
Thomas Heartman
28d7672a58
feat: batch week data if the shown time span is greater than 12 weeks. (#10745)
Implements batching of data points in the archived:created chart: when
there's 12 or more weeks of data, batch data into batches of 4 weeks at
a time. When we batch data, we also switch the labeling to be
month-based and auto-generated (cf the inline comment with more
details).

<img width="798" height="317" alt="image"
src="https://github.com/user-attachments/assets/068ee528-a6d6-4aaf-ac81-c729c2c813d1"
/>


The current implementation batches into groups of 4 weeks, but this can
easily be parameterized to support arbitrary batch sizes.

Because of the batching, we also now need to adjust the tooltip title in
those cases. This is handled by a callback.
2025-10-07 13:51:45 +02:00
Mateusz Kwasniewski
5e2d95e0be
refactor: move release plan schemas to OSS (#10748) 2025-10-07 12:28:28 +02:00
Tymoteusz Czech
f01f747c9b
chore: update openapi (#10747) 2025-10-07 10:27:54 +00:00
Tymoteusz Czech
3393bb35e5
feat: update invoice billing components (#10740) 2025-10-07 10:35:40 +02:00
Fredrik Strand Oseberg
ce1fb144d7
feat: add milestone progression automation UI (#10743) 2025-10-07 10:30:36 +02:00
Gastón Fournier
bade23974e
feat: allow test operation for patch (#10736)
## About the changes
This would allow users to add test statements to protect from concurrent
modifications. From
https://github.com/orgs/Unleash/discussions/10707#discussioncomment-14602784

E.g.
If you had this feature flag configuration
```
{
  "name": "flexibleRollout",
  "constraints": [
    {
      "contextName": "a",
      "operator": "IN",
      "values": [
        "100", "200", "300", "400", "500"
      ],
      "caseInsensitive": false,
      "inverted": false
    }
  ],
  "parameters": {
    "rollout": "100",
    "stickiness": "default",
    "groupId": "api-access"
  },
  "variants": [],
  "segments": [
    122
  ],
  "disabled": false
}
```

And you'd like to remove the value 300 from the constraints, you'd have
to first get the current values and then PATCH the strategy with the
following body:
```
[{ "op": "remove", "path": "/constraints/0/values/2" }]
```

This could fail in case of concurrent modifications (e.g. if someone
removed the value "100", then the index to remove "300" will no longer
be 2).

With the test operation, you'd be able to add a protection mechanism to
validate that the value at index 2 is still 300:
```
[
    { "op": "test", "path": "/constraints/0/values/2", "value": "300" },
    { "op": "remove", "path": "/constraints/0/values/2" }
]
```
If the test fails, the remove operation will not be applied.

I've tested this locally and works as expected:
1. If the value is still 300, it will remove it
2. The operation will fail if the value is no longer 300 because of
another change.
2025-10-06 16:52:10 +02:00
Tymoteusz Czech
44882d52b4
chore: update openapi frontend types (#10739) 2025-10-06 13:26:56 +00:00
Mateusz Kwasniewski
c3491abf4b
feat: milestone progressions migration (#10738) 2025-10-06 13:47:02 +02:00
Thomas Heartman
236addbe23
fix: show average ratio for the period of collected data (#10735)
Instead of showing the current ratio of archived to created flags, we
show you the average ratio for the selected period.

Before:
<img width="1153" height="391" alt="image"
src="https://github.com/user-attachments/assets/efe87982-544e-485a-aa4d-04faa7d552fc"
/>

After:
<img width="1143" height="385" alt="image"
src="https://github.com/user-attachments/assets/25f8ee4d-3eaa-4e01-a793-2cc0321a55ed"
/>
2025-10-06 13:05:21 +02:00
Gastón Fournier
b1f4ebd5eb
chore: return user id alongside max updated_at (#10732)
This is for internal use
2025-10-06 11:43:40 +02:00
David Leek
c39b4cd1b0
feat: add a suggestion banner at the bottom of empty feature-environments (#10725) 2025-10-06 09:02:15 +02:00
Mateusz Kwasniewski
c65a336783
feat: milestone start time update (#10730) 2025-10-03 14:09:49 +02:00
Mateusz Kwasniewski
f670505e56
feat: milestones started at migration (#10729) 2025-10-03 13:38:32 +02:00
Mateusz Kwasniewski
3ef2a7f93b
feat: add histogram to impact metrics (#10728) 2025-10-03 10:13:12 +02:00
Tymoteusz Czech
adada932b9
fix: clearing lifecycle filter when switching to archived view (#10726)
"Lifecycle" filter should never be enabled when viewing archive.
2025-10-03 09:29:02 +02:00
Gastón Fournier
a927f1f42b
chore: new method that considers users updated at the same time (#10723)
We could have users updated at the exact same time, so we need to
include that timestamp in the next fetch to avoid missing users, but
also include the latest user id so we can exclude the ones already
fetched.

The following test shows how to process pages with this new method:

c03df86ee0/src/lib/features/users/user-updates-read-model.test.ts (L39-L65)
2025-10-03 09:24:53 +02:00
Tymoteusz Czech
1e5de5b8b7
feat: new invoice billing page view (#10721)
Mockup of more detailed summary of used traffic on hosted offer.
See previous PR #10718
2025-10-03 07:24:27 +00:00
Tymoteusz Czech
9b5324ac92
feat: flag traffic billing display feature (#10718)
Feature flag and initial changes in Billing UI
2025-10-03 09:18:39 +02:00
Nuno Góis
df67c041fc
chore: new confirmation dialog for replacing release plans (#10720)
https://linear.app/unleash/issue/2-3931/add-a-confirmation-dialog-when-replacing-existing-release-plan

Adds a confirmation dialog when replacing an already active release
plan.

<img width="706" height="325" alt="image"
src="https://github.com/user-attachments/assets/f682809c-f563-4dca-9924-be1e9188c698"
/>
2025-10-02 15:48:27 +01:00
Mateusz Kwasniewski
6c6d4c0ccc
chore: milestone progression flag (#10719) 2025-10-02 14:28:37 +02:00
Gastón Fournier
fb5d4cc7a1
fix: constraints should not be null (#10717)
## About the changes
In our code, we're not expecting constraints to be null:
https://github.com/search?q=repo%3AUnleash%2Funleash%20jsonb_array_elements(constraints)&type=code

It's unlikely to get a null value in constraints when using our API or
UI, but there might be cases where this can happen, as we saw in our
logs:
```
error: select "context_fields"."name", "context_fields"."description", "context_fields"."stickiness", "context_fields"."sort_order", "context_fields"."legal_values", "context_fields"."created_at", COUNT(DISTINCT CASE
                        WHEN features.archived_at IS NULL
                        THEN feature_strategies.project_name
                    END) AS used_in_projects, COUNT(DISTINCT CASE
                        WHEN features.archived_at IS NULL
                        THEN feature_strategies.feature_name
                    END) AS used_in_features from "context_fields" LEFT JOIN feature_strategies ON EXISTS (
                        SELECT 1
                        FROM jsonb_array_elements(feature_strategies.constraints) AS elem
                        WHERE elem ->> 'contextName' = context_fields.name
                      ) left join "features" on "features"."name" = "feature_strategies"."feature_name" group by "context_fields"."name", "context_fields"."description", "context_fields"."stickiness", "context_fields"."sort_order", "context_fields"."created_at" order by "name" asc - cannot extract elements from a scalar
```
which is likely due to:
`jsonb_array_elements(feature_strategies.constraints)` with null
constraints

For this reason, it seems reasonable to enforce the constraint at the
database level.
2025-10-02 12:45:53 +02:00
dependabot[bot]
562f7c5aaa
chore(deps): bump vite from 6.3.5 to 6.3.6 (#10642) 2025-10-02 11:45:02 +02:00
Tymoteusz Czech
f5af92b5ee
feat: change "archived" flags filter placement on project flags list (#10710)
Archived flags link will now it will show up on the right side, next to
import/export, which makes it more in line with flags overview.

Co-authored-by: Thomas Heartman <thomas@getunleash.io>
2025-10-02 11:44:57 +02:00
unleash-bot[bot]
da22cb0d65
chore(AI): etagVariant flag cleanup (#10714)
This PR cleans up the etagVariant flag. These changes were automatically
generated by AI and should be reviewed carefully.

Fixes #10711

## 🧹 AI Flag Cleanup Summary
This PR removes the `etagVariant` feature flag, making the versioned
ETag format
(`v2`) the default and only behavior for the client features API.
### 🚮 Removed
- **Feature Flag**
- Removed the `etagVariant` flag definition from `experimental.ts`.
- Removed conditional logic for ETag generation in
`client-feature-toggle.controller.ts`.
- **Testing**
- Removed parameterized tests for both states of the flag in
`feature.optimal304.e2e.test.ts`.
- Removed configuration of the `etagVariant` flag in test setup.
### 🛠 Kept
- **ETag Generation**
- The logic to generate ETags with a version suffix (`v1`) is now the
standard
behavior.
- **Testing**
- Tests have been updated to exclusively assert the presence of the `v1`
suffix in ETags.
### 📝 Why
The `etagVariant` feature flag has been successfully rolled out and is
now
considered complete. By removing the flag, we are simplifying the
codebase by
eliminating conditional paths and making the improved ETag format
permanent.
This change ensures all client API responses for features include a
versioned
ETag, which helps with cache-busting when the ETag format changes in the
future.

---------

Co-authored-by: unleash-bot <194219037+unleash-bot[bot]@users.noreply.github.com>
Co-authored-by: Gastón Fournier <gaston@getunleash.io>
2025-10-02 11:26:53 +02:00
Mateusz Kwasniewski
c2b598d8d9
refactor: centralize number formatting (#10716) 2025-10-02 09:36:27 +02:00
Mateusz Kwasniewski
921130a9c0
fix: impact metrics formatting (#10715) 2025-10-01 16:33:58 +02:00
Tymoteusz Czech
b409cc8034
feat: add placeholder for empty change requests table (#10706) 2025-10-01 14:22:04 +02:00
Tymoteusz Czech
c7eb79038e
chore: add flags for UI filter refactor (#10708) 2025-10-01 09:20:25 +00:00
Nuno Góis
7462465a0b
chore: resource limits service (#10709)
https://linear.app/unleash/issue/2-3927/implement-resource-limits-service

Implements a resource limits service.

The implementation looks trivial (or even redundant) in OSS, but by
implementing a resource limits service we can make this potentially
dynamic and overridable.
2025-10-01 09:57:18 +01:00
Tymoteusz Czech
9d996f14d9
feat: improve flag filters on project page (#10705) 2025-10-01 10:11:02 +02:00
Tymoteusz Czech
c12aca72db
Refactor flag filters (#10703)
Refactored and simplified code around flag filters, in preparation for
UI improvements. It's split into 2 PRs in order to simplify what needs
to be behind a flag and what doesn't.

- `ExperimentalColumnsMenu` moved to `ColumnsMenu`, old unused
`ColumnsMenu` removed
- Parts of the code moved to `ProjectFeaturesColumnsMenu`
- Moved `FlagCreationButton` to a separate file
- Removed part behind archived flag (`projectOverviewRefactorFeedback`)
2025-10-01 09:30:36 +02:00
Nuno Góis
e46f8881d1
chore: extract UI config logic into its own service (#10704)
https://linear.app/unleash/issue/2-3921/extract-ui-config-logic-into-its-own-service

Extracts UI config logic into its own service.

This is the first step to accomplish resource limits and license key
resources alignment.
2025-09-30 11:04:20 +01:00
Nuno Góis
b865ee44f3
chore: address UX feedback for add strategy modal (#10698)
https://linear.app/unleash/issue/2-3911/address-new-ux-feedback

Addresses UX feedback regarding new "add strategy" modal:
- "View more strategies" instead of "View more"
- Avoid horizontal scroll
- Fix responsiveness
- Prevent flicker when navigating between strategy and preview modals
2025-09-26 14:54:08 +01:00
Thomas Heartman
99c4f7111a
feat: add change request table filter buttons (#10679)
Adds filter buttons for filtering between "CRs created by me" and "CRs
where I've been requested as an approver".

The current implementation is fairly simplistic and the buttons are not
connected to the actual table state directly (instead being set up with
their own simple state and onChange hooks), but it covers the simple
scenario. I want to defer a more complex solution until we know we need
it and until we know exactly what we need. The implementation is based
on the lifecycle filters that we have on the project flags page.

The current logic is such that: when you land on the page, there's no
query params in the URL, but the data fetch applies `createdBy:IS<your
user>`. If you switch to "approval requested" (and back again), the URL
will reflect this.

For reference, the github workflow works like this, where each URL has a
set of default filters, e.g.:
- `/pulls`: `is:open is:pr assignee:thomasheartman archived:false`
- `/pulls/review-requested`: `is:open is:pr
review-requested:thomasheartman archived:false`

But if you change the default filters or add new ones, the URL will
update to `pulls?<query-string>` (e.g.
`/pulls?q=is%3Aopen+is%3Apr+review-requested%3Athomasheartman+archived%3Atrue`)

So this takes a similar approach, but better suited to the way we do
tables in general.

Rendered:

<img width="1816" height="791" alt="image"
src="https://github.com/user-attachments/assets/60935900-488d-4ca9-b110-39f3568a08a6"
/>

<img width="1855" height="329" alt="image"
src="https://github.com/user-attachments/assets/5e865a2e-8fdc-41ab-ba38-bbe6776d04ad"
/>
2025-09-26 12:42:47 +02:00