* Replace legacy access control logic with app platform api
* Update virtual folders paths
* Better virtual folder handling
* Update for real access call for virtual folders
* Don't call parent API endpoint when virtual folder
* Provisioning: drop stale and duplicate watch events in the list cache
The shared RTK Query watch handler upserted events by metadata.name
without comparing resourceVersion, so with multiple interleaved watch
streams (HA delivery, reconnect replays) a late older object could
overwrite newer cached state, and duplicate deliveries caused redundant
store updates and re-renders. Compare resourceVersions and skip events
that are not newer than the cached item, failing open when either
version is missing or non-numeric.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Provisioning: rewrite watch handler tests on the MSW harness
Drive the real useListJobQuery({watch: true}) flow through
setupProvisioningMswServer and MockGrafanaLiveSrv watch events instead
of mocking ScopedResourceClient directly.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* Navigation: Show starred folders in the Starred nav section
Folders join dashboards in the nav Starred list when starredFoldersEnabled()
(grafana.starredFolders + starsFromAPIServer + foldersAppPlatformAPI).
Per-kind icons (apps/folder) and dashboards-before-folders ordering make
same-named items distinguishable; both are gated on the feature so the nav
is byte-identical while it is off.
* Navigation: Keep starred nav order stable on rename, announce kind on starred icons
Review feedback: updateDashboardName sorted pure-alphabetically, re-interleaving
starred folders among dashboards until the next sync; a same-named folder/dashboard
pair read as two identical links to screen readers. A shared comparator and icon
titles fix both; new tests pin the rename ordering and the flag-off folder guard.
* Navigation: Fix stale starred nav on folder delete and failed star
Deleting a starred folder left its nav row behind, and a
server-rejected star mutation still updated the nav; with no
reconcile path the wrong state persisted until reload.
* Navigation: Only un-star folders the bulk delete actually removed
The un-star loop ran for every requested folder, clearing starred nav
entries even when the delete was skipped (provisioned folder) or failed.
Dispatch per folder on delete success instead.
* Navigation: Update starred folder label on rename
Browse-tree refetches don't touch the mounted Starred nav row, so a
renamed folder kept its old label until remount. Dispatch
updateDashboardName (as dashboard saves already do) from both folder
rename paths: legacy saveFolder and app-platform useUpdateFolder.
* Navigation: Keep starred nav sync scoped by kind
The sync search matches the starred uid union against both kinds, so
a starred dashboard rendered a bogus folder row when an unstarred
folder shared its uid, and a uid starred as both kinds rendered twice.
Filter hits against the per-kind star sets and dedupe the union.
Also from review: collapse setStarred's inline payload type into
StarredNavItem, and import the API group ids from @grafana/api-clients
instead of hardcoding them.
* Stars: Add kind-aware usage analytics
The legacy grafana_dashboards_star_dashboard event carried no kind, so
folder stars were indistinguishable from dashboard stars. Replace it
with typed grafana_stars_item_starred (defineFeatureEvents) and enrich
grafana_navigation_item_clicked with itemIsStarred/itemKind to measure
starred-folder click-through.
When foldersAppPlatformAPI is enabled the UI creates folders via the K8s
folder API instead of POST /api/folders. Root-level creates must include
the ephemeral grafana.app/grant-permissions annotation so default RBAC
permissions are written under kubernetesAuthzResourcePermissionApis.
Fixesgrafana/grafana#126964
* Scopes: Fix sync-from-enterprise.sh script bugs
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Scopes: Regenerate frontend API client for default scope endpoint
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(provisioning): add duplicate-path validation to ResourceEditFormSharedFields
- Add async validatePath that checks for existing files at the target path
- Add MSW handler for files/:path returning 404 for test coverage
- Migrate ResourceEditFormSharedFields tests to MSW
* chore(i18n): extract translation strings
* fix(provisioning): always-fresh path check + correct RHF deps direction
Address PR review feedback on ResourceEditFormSharedFields:
- Remove preferCacheValue=true on the pre-save existence check; cached
404/200 results can be stale by the time the user submits.
- Swap the deps direction. RHF triggers a field's deps when *that field*
changes, so 'deps: [ref]' on path meant 'when path changes, validate
ref' (the opposite of intent). Move 'deps: [path]' onto the ref field
so branch changes correctly re-run validatePath.
* fix(folders): guard against null display/keys in combineFolderResponses
The DisplayList type declares display and keys as required arrays,
but the IAM display mapping API can return null for either field.
Without optional chaining on these properties, indexing into null
throws TypeError: Cannot read properties of null (reading '0'),
crashing every folder page when foldersAppPlatformAPI is enabled.
* wip
* fix(annotations): optional AnnotationTagList.items, tighten comments, add scope tests
- AnnotationTagList.items is now optional (defensive ?? [] implies it can be absent)
- Replace multi-line comment blocks with single-line inline comments per codebase style
- Add scope-forwarding tests to setDashboardPanelContext: verify scopes from
sceneGraph.getScopes() are included in k8s create/update request spec
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(annotations): wire k8s app installer to FF, fix tags shape, fix ID normalisation
- Register annotation app installer when kubernetesAnnotations FF is on
(previously only cfg.AnnotationAppPlatform.Enabled=true triggered it,
leaving all routes as 404 when only the FF was set)
- Fix AnnotationTagList/AnnotationTagItem to match backend shape
({tags:[{tag,count}]} not {items:[{name,count}]}) and update the
term mapping in K8sAnnotationServer.tags()
- Add toK8sName(id: string|number) to normalise legacy numeric IDs
(e.g. 23 or "23") to the k8s "a-{id}" prefix required by parseAnnotationID;
apply it to both update (GET fetch-then-merge) and remove (DELETE)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(annotations): route dashboard query through k8s /search sub-resource
When kubernetesAnnotations is on, dashboard annotation queries now hit
/apis/annotation.grafana.app/v0alpha1/namespaces/{ns}/search instead of
the legacy /api/annotations endpoint:
- Add annotationK8sClient.search() with param translation (matchAny → tagsMatchAny,
panelId → panelID, tags[] → repeated tag) and AnnotationList → AnnotationEvent[] mapping
- Route K8sAnnotationServer.query through search; forAlert stays on legacy because
ListOptions has no Type/AlertUID filter on the backend
- Strip the "a-" prefix on the way out so consumers see legacy-shaped ids
- Use loose Record<string, unknown> + typeof narrowing instead of type assertions
- Update setDashboardPanelContext.test to assert the a-{id} prefix the new path produces
AnnoListPanel still uses /api/annotations directly because it depends on
identity fields (login/email/avatarUrl) and a userId filter that the new
spec/endpoint don't expose; migrating it requires backend changes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(annolist): migrate AnnoListPanel to k8s API with IAM identity hydration
When kubernetesAnnotations is on, the Annotations List panel now hits
/apis/annotation.grafana.app/v0alpha1/namespaces/{ns}/search and hydrates
identity fields (userId/login/email/avatarUrl) via the IAM /display endpoint:
- Expose createdBy ("user:<uid>") on AnnotationEventResource by reading
metadata.annotations["grafana.app/createdBy"] in annotationToEvent
- Branch AnnoListPanel.doSearch on the FF: legacy /api/annotations stays for
FF-off; FF-on routes through annotationK8sClient.search() then a single
batch call to /apis/iam.grafana.app/v0alpha1/.../display to resolve
displayName/avatarURL/internalId for every unique createdBy key
- queryUser carries the uid so subsequent searches filter via createdBy:user:{uid}
- displayName substitutes for both login (gates avatar) and email (tooltip text)
since /display doesn't return email
No backend changes required.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(annolist): hydrate email via per-user IAM User resource fetch
The IAM /display batch endpoint deliberately omits email, so previously we
substituted displayName for email in the "Created by" tooltip. The User
resource (GET /apis/iam.grafana.app/v0alpha1/namespaces/{ns}/users/{uid})
exposes spec.email, so we now fetch it per unique createdBy uid in parallel
with the /display batch. On per-user fetch failure (e.g. viewer without
iam:users:get) we fall back to displayName so the tooltip still has a label.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(annotations): drop backend FF + installer wiring (moved to separate PR)
All kubernetesAnnotations feature toggle artifacts (Go registry +
generated Go/CSV/JSON + generated TS) and the pkg/registry/apps/apps.go
installer wiring live on branch mdv/annotations-k8s-feature-flag and ship
as a separate PR. Frontend and backend deploy at different cadences, so
they cannot share a PR.
This branch references config.featureToggles.kubernetesAnnotations, so
the backend PR must merge first before this one will typecheck on main.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* rename(annotations): kubernetesAnnotations FF → kubernetesAnnotationsClient
Mirrors the backend rename. Updates config.featureToggles checks, test
toggle assignments, and a few comment references.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* TEMP: force kubernetesAnnotationsClient FF on for local testing
Backend FF PR (mdv/annotations-k8s-feature-flag) is in review, so the FF
isn't yet defined on main. Hardcode both check sites (AnnoListPanel.tsx
and features/annotations/api.ts) to always take the new k8s path so the
client can be exercised without the FF.
Revert this commit once the backend lands.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(annotation client): drop test-only reset hatch
ScopedResourceClient construction is just a getAPINamespace() call plus
a string concat, so memoizing it wasn't earning much, and the cache
forced a resetAnnotationK8sClientForTests test-only export. Drop the
cache and construct on each call; the export and its lone caller in
resetAnnotationServerForTests go away.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* revert(annolist): drop per-user IAM fetch for email
Earlier we added a per-user GET /apis/iam.grafana.app/v0alpha1/namespaces/{ns}/users/{uid}
to read spec.email. In practice that 404s in the test environment (likely
a namespace/scope mismatch on the IAM apiserver), and even when it 403s
the failed request shows up in the browser console. The /display
batch already gives us displayName, so revert to using it for the email
substitute as before.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(annotations): switch FF gate to config.annotationAppPlatformEnabled
The backend now exposes [annotations.app_platform] enabled via the
bootstrap settings DTO (see mdv/annotations-k8s-feature-flag), so the
frontend reads config.annotationAppPlatformEnabled instead of a feature
toggle. Removes the TEMP force-on hack since the real config can be
flipped via grafana.ini.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(annotation server): drop test-only reset hatch
Both AnnotationServer implementations are stateless wrappers around
backend calls, so memoizing the chosen instance wasn't earning much,
and the cache forced a resetAnnotationServerForTests test-only export.
Drop the cache and construct on each call; the export and its callers
in api.test.ts and setDashboardPanelContext.test.ts go away. The empty
beforeEach blocks left behind in the dashboard test are removed too.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* cleanup
* feat(annotations): forward selected scopes on the search/query path
Read paths previously omitted scopes, so the backend returned every
annotation regardless of the dashboard's selected scope. Two call sites
now source scopes the same way the create/update path already does:
- GrafanaDatasource.getAnnotations: when options.dashboard is a
SceneObject, mirror SceneQueryRunner via sceneGraph.getScopes(...).
Gated on config.annotationAppPlatformEnabled so the legacy
/api/annotations endpoint never sees the param.
- AnnoListPanel: read this.context?.state.value via ScopesContext (class
contextType), forward to annotationK8sClient.search. Already only ran
in the k8s branch, so legacy is unaffected.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(annotations): forward request.scopes to getAnnotations on the panel path
The previous attempt sourced scopes from options.dashboard via
sceneGraph.getScopes, but on a scenes dashboard options.dashboard is the
legacy DashboardModel returned by getDashboardSrv().getCurrent(), so
isSceneObject(...) is false and scopes never get added.
The scenes AnnotationsDataLayer's standardAnnotationQuery already
populates request.scopes via sceneGraph.getScopes(layer) before calling
datasource.query(). Thread that through into getAnnotations so /search
sees the scope filter on the dashboard panel annotation path. The
options.dashboard sceneGraph path stays as a fallback for direct callers
that don't go through query().
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(annolist): re-run search when ScopesContext value changes
ScopesContext exposes a stable Provider value, so static contextType +
React re-render didn't fire on scope changes (panels work via the
scenes-side imperative setContext/observable path). Subscribe to
stateObservable in componentDidMount and re-run doSearch when the joined
scope-name key differs from the last one we queried with. The replay-on-
subscribe initial emission is filtered out via the lastScopeKey written
during the first componentDidMount-driven doSearch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* cleanup
* fix
* flag it behind both new api being enabled and fe client ff
* fixes
* prettier + fix test
* typecheck
* keep alert anno legacy call since new API does not yet fetch those
* use PATCH + api discoverability
* fix
* fix ff
* refactor
* rename
* fix
* use PATCH for update
* reusable discoverability util
* fix
* fix
* policybot
* make gen toggles
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Force refetch for team folders folder in browse dashboards
* Always show team folders folder
* Move the refresh into the new API
* Hide behind feature flag
* Make sure team folder are only on the first page
* Fix circular dep
* fix import
* Break import cycle
* Add team msw handler
* Add notifications for create/delete, organize notification translations
* test the notification was successfully constructed
* Use standard for error handling
* lint cleanup
* Provisioning: Add polling fallback when WebSocket watch streams are unavailable
* refactor: move connection failure handling to centrifuge service layer
Move connection timeout and liveEnabled detection from
ScopedResourceClient.watch() into CentrifugeService where the hang
originates:
- initChannel: Promise.race the connectionBlocker against a 10s timeout
so channels that never connect get shutdownWithError instead of
hanging forever.
- getChannel: when liveEnabled=false, immediately shutdownWithError
without creating a subscription or waiting for the timeout.
This lets watch() use a clean pipe chain (map → filter → map →
catchError) instead of a 45-line Observable wrapper with manual timer
and subscription management.
Add centrifuge service tests for the two new behaviors.
* add comment to connection timeout Promise.race
* remove excessive comments from service test
* document known limitation: first poll can't detect deletions during race window
* Separate creation of the folder with results in cards
* Put card into separate component
* Extract the card to separate file
* Change to alert component instead
* Clean up the card creation
* Pass showSuccessAlert in the createTeam
* Simplify the error handling
* Use request component pattern
* Revert "Use request component pattern"
This reverts commit 8a2acaa220.
* Decompose and refactor the api calls
* Rename api calls file
* Initial tests for the API calls
* Comments and small refactor
* Add icon to success link
* Better text messages
* translations
* showSuccessAlert handling
* Small improvements to state reporting
* Add default role handler and update tests
* Test fixes
* Catch the error in onQueryStarted
* Fix tests
* Put handlers into helper functions
* Move helper handlers to packages
* remove unused import
* Add translation
* Update lint workers
* simplify types
* remove unused imports
* Fix import
* generics again
* rollback ci changes
* Add reporting
* Address review comments
* Fix tests
* Fix owner ref creation bug
* Fix lint ci change
Adds `depth` and `rootScope` query parameters to `scope_navigations` and
`scope_dashboard_bindings` API requests, enabling the backend to return
contextual results for nested scope navigation.
**`depth`**: Nesting level in the rendered navigation tree. Omitted at
depth 0 (top-level request). Calculated as `path.length - 1` where path
includes the root `''` key — e.g. `['', folderA]` → depth 1.
**`rootScope`**: The top-level scope the navigation tree was built for
(`forScopeNames[0]`). Omitted on the root request; present on all
sub-scope expansion requests. Uses `forScopeNames` rather than
`navigationScope`, which is UI state only set when navigating to a
dashboard under a sub-scope.
Both params use truthy checks so depth 0 and empty rootScope are stripped
before the HTTP request is made.
Also removed stale 'name' field from the gen file.
Remove the spurious `name` field from the generated scope find
endpoint arg types and the `name: ''` workarounds in ScopesApiClient.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Provisioning: Show watch error to user + fallback to polling
When Grafana Live watch streams fail (e.g., with anonymous auth enabled),
the branch dropdown in the Provisioning Wizard step 2 loads forever because
useRepositoryStatus waits for reconciliation via the broken watch stream.
This change:
- Widens the onError callback signature in createOnCacheEntryAdded to receive
dispatch and arg, allowing handlers to react to watch failures
- Adds polling fallback (every 5s) to listRepository and listConnection
- Shows a warning notification only if polling itself fails, avoiding noise
when the fallback mechanism works
The user still gets data updates (via polling instead of real-time watch), and
only sees an error message if both watch AND polling fail.
* Provisioning: Fix watch permission error for anonymous users
Allow anonymous users to subscribe to watch streams by assigning them
an 'anonymous' user ID instead of rejecting with a permission error.
Simplify the watch error handler to show a notification without
polling fallback, which was causing redundant requests.
* Provisioning: Add "Fix Folder IDs" button + isFetching→isLoading fix
- Fixed `useFolderMetadataStatus` to use `isLoading` instead of `isFetching` for better UX (prevents flash on background refetches)
- Extended `useFolderMetadataStatus` return type to include repository name (needed for fix job API calls)
- Created `useFixFolderMetadata` hook to trigger fix-folder-metadata jobs with loading state UI
- Added "Fix folder IDs" button to folder permissions drawer via `MissingFolderMetadataBanner`
- Added repo-level warning banner on Repository Overview page when folders lack metadata
- Created `useRepoHasMissingFolderMetadata` hook to detect missing metadata at repository level
- Added `hasMissingFolderMetadata` utility function to tree builder
- Added success/error notifications for fix-folder-metadata job actions
- Updated i18n strings and tests
* Remove fixFolderMetadata success toast, merge banner components
- Remove "Fix folder metadata job started" notification — button
already shows loading state via job watching
- Merge MissingFolderMetadataBanner and RepoMissingFolderMetadataBanner
into a single component with a `variant` prop ('folder' | 'repo')
* Fix useFolderMetadataStatus tests for object return type
Update assertions to use result.current.status instead of
result.current, and change isFetching mock to isLoading.
* Consolidate useRepoHasMissingFolderMetadata into useFolderMetadataStatus
Extend useFolderMetadataStatus with a repo-level overload that accepts
{ repositoryName } and checks the full files listing for missing
_folder.json metadata, replacing the separate useRepoHasMissingFolderMetadata
hook and hasMissingFolderMetadata tree utility.
* Split useFolderMetadataStatus into two focused hooks
Extract repo-level metadata check into useRepoMetadataStatus, restoring
useFolderMetadataStatus to its original single-folder purpose. Each hook
now has its own test file with no cross-mock overhead.
* Move fixFolderMetadata error handling into hook, simplify feature toggle check
* Fix false positives in repo-level metadata check, prevent duplicate job submissions
checkFilesForMissingMetadata now uses resource data to only check provisioned
folders (resource type 'folders') instead of inferring folders from file paths.
This eliminates false positives where root _folder.json was required even when
root wasn't a provisioned folder.
Also adds 'pending' state to job-running checks in useFixFolderMetadata and
SyncRepository to prevent duplicate job submissions between mutation completion
and job transition to 'working'.
Tests migrated from jest.mock to MSW per project conventions.
* Break circular dependency between folderMetadata and treeUtils
Check resources directly against file paths instead of using
mergeFilesAndResources, which imports from treeUtils (which itself
imports getFolderMetadataPath from folderMetadata).
* Add unit tests for checkFilesForMissingMetadata
* Add success notification when folder metadata fix job is submitted
Notifies the user that the fix has started and will continue in the
background, so they know it's safe to navigate away.
* Generate quotas API client
* Browse: Add quota limit banners for dashboards and folders
Display warning/error banners on the Browse Dashboards page when users
approach or reach their dashboard/folder creation quotas. Gated behind
the kubernetesUnifiedStorageQuotas feature toggle.
- Extract quota fetching and state calculation into useQuotaLimits hook
- Warning banners are dismissable (persisted via localStorage); error banners are not
- Show "Request quota extension" button for paying users
- Add comprehensive test coverage (22 tests)
* Browse: Improve quota banners with cache invalidation and split alerts
- Wire up RTK Query cache invalidation so quota data refreshes on
resource create/delete (dashboards, folders)
- Use granular tag invalidation for delete mutations to avoid 404s
- Show separate alerts for error (at_limit) and warning (nearing)
- Follow i18n best practices: Trans for JSX children, t() for props
- Use type guard instead of `as` assertion per lint rules
* Browse: Extract shared invalidateQuotaUsage helper and rewrite tests
- Export invalidateQuotaUsage(dispatch) from quotas API package
- Use shared helper in browseDashboardsAPI and folder hooks
- Rewrite QuotaLimitBanner tests with getByRole assertions,
inline data, and organized by severity
* Browse: Use Alert buttonContent for extension button, position dismiss in top-right
- Use onRemove + buttonContent props to render extension button in
Alert's native action slot
- Position dismiss IconButton absolutely in top-right corner
- Always show dismiss button regardless of tier
- Tighten tests: use within() for scoped getByRole queries
* Update tests
* comments
* Fix percentage rounding, remove unnecessary quota invalidation and wrapper style
Use Math.floor instead of Math.round so percentage only shows 100% when
usage equals the limit. Remove quota invalidation from saveDashboard since
it only edits existing dashboards. Drop redundant wrapper div with
position: relative since Alert already provides it.
* Only invalidate quota usage on new dashboard creation and simplify early return
Conditionally invalidate quota cache in saveDashboard only when
data.version === 1 (new dashboard). Simplify QuotaLimitBanner by
computing atLimit/nearing arrays directly and early-returning when
both are empty.
* Use generated GetUsageResponse type and remove manual type guard
The quotas API client now includes proper typed GetUsageResponse with
usage and limit fields, so the manual QuotaUsageResponse interface and
isQuotaUsageResponse type guard are no longer needed.
* Extract shared invalidateListOnSuccess and extensionProps to reduce duplication
* Use tuple iteration to build resource statuses in useQuotaLimits
* Address PR review: rewrite tests with MSW and use API_GROUP constants
- Rewrite QuotaLimitBanner tests to use MSW handlers instead of mocking hooks
- Add quotas.grafana.app MSW handler to grafana-test-utils
- Use testWithFeatureToggles utility for feature flag management
- Use user from render result instead of importing userEvent
- Use API_GROUP constants from API clients in useQuotaLimits
* Deduplicate QuotaLimitBanner test helpers and use shared constants
- Extract usageResponse() and expectNoAlert() helpers to reduce repetition
- Consolidate mockError() into mockErrorForResource() with optional params
- Use testWithFeatureToggles for the flag-off test instead of manual config override
- Use DASHBOARD_API_GROUP/FOLDER_API_GROUP constants instead of hardcoded strings
- Import QUOTAS_USAGE_URL from @grafana/test-utils/handlers instead of local constant
* Rename hasError to allQueriesFailed for clarity
The condition uses && (both queries must fail), so hasError was misleading
since it sounds like any single error would qualify.
* Revert handlers/index.ts re-export; use local QUOTAS_USAGE_URL constant
* Re-export QUOTAS_USAGE_URL from @grafana/test-utils/handlers
Follow the same pattern as PROVISIONING_API_BASE instead of
using a local constant in the test.
* Add quotas.grafana.app OpenAPI spec snapshot
* fix: prevent auto-sync race condition in provisioning quota tests
Use SkipSync to prevent controller auto-sync from racing with file
copy, matching the pattern in sync_quota_test.go. Without this, the
auto-sync could read partially-written files and pollute quota tracker
stats with the root folder before the explicit sync runs.
* chore: add overrides.yaml to gitignore and update OpenAPI specs
Ignore overrides.yaml and regenerate API clients to pick up
correlations and IAM spec changes from main merge.
* rtkq/quotas: gate quota invalidation behind feature toggle
* WIP
* Make transformations properties optional, create correct object for partial spec
* update the generated client type, fix logic for submission of transformations
* Update readme with what is needed for updating the client
* Move logic to utils, add test
* Add tests to increase coverage
* continue to build out test coverage
* Add tests
* Add create correlation
* WIP improve function coverage
* fix test
* wip add notification on edit
* Moving directories
* Move back as we are no longer rendering with a wrapper
* Run the generator
* APIServer: Surface watch errors in the UI
When watch API calls fail (e.g., for non-admin users), errors are now propagated through the Observable pipeline and displayed as toast notifications, preventing the UI from appearing stuck during bulk operations.
* pass error status
* Set error status on job when watch fails instead of clearing items
When a WebSocket watch fails, set the job's status to error with the
error message instead of clearing cached items. This keeps the job
in cache so JobContent renders the error naturally via onStatusChange,
rather than falling through to FinishedJobStatus which shows a
misleading "No job found" error.
* Add back admin-only watch restriction for testing
Temporarily limit watch subscriptions to admin users while testing
provisioning repositories. This needs to be removed later.
* Use ErrorPermissionDenied and add clarifying comments
- Map SubscribeStreamStatusPermissionDenied to centrifuge.ErrorPermissionDenied
(code 103) instead of ErrorUnauthorized for correct semantics
- Document why RxJS retry is not needed on the live channel path
- Document the listJob onError cache mutation logic
* Simplify createOnCacheEntryAdded error handling
Remove notification logic and dispatch from the error handler.
Consumers now own error handling entirely via the onError callback.
* Remove admin-only watch restriction
Remove the temporary admin-only gate on watch subscriptions that was
used for testing.
* Provisioning: Remove domain restrictions for GitHub, GitLab, and Bitbucket URLs
Allow self-hosted instances (GitHub Enterprise, self-managed GitLab, self-hosted
Bitbucket) to use provider-specific connectors instead of requiring the generic
git connector. Consolidate URL validation into shared config, apply generic
domain-stripping to all providers, and remove dead code.
* Provisioning: Move httpUtils to api/clients/provisioning/utils
Move the provisioning error helper to its new home alongside the other
provisioning API client utilities.
* Apply suggestion from @hugohaggmark
Co-authored-by: Hugo Häggmark <hugo.haggmark@gmail.com>
* Stricter i18n sorting
---------
Co-authored-by: Hugo Häggmark <hugo.haggmark@gmail.com>
Co-authored-by: Andrej Ocenas <mr.ocenas@gmail.com>
What is this feature?
This PR introduce refactoring for role picker for teams and users. It uses RTK Query.
The related task: grafana/identity-access-team#1821
The previous PR with related logic: #113783
Why do we need this feature?
This refactoring is a cleaner way for handing refetching.
* Provisioning: Do not disable "next" button on form errors
* Handle errors from dryRun
* Show field errors for app step in Wizard
* Cleanup
* Fixes
* use existing util
* Revert isNextDisabled changes
* memoize sorted items
* Do not disable on finish step
* Show all errors
* Separate fetching and loading
* Add revalidate mode
* Tighten the types
* Provisioning: Add dryRun validation for Connection resources
Validate connection configuration before saving by calling the create/replace endpoint with dryRun=true. This mirrors the repository test endpoint behavior and returns field-level validation errors that are displayed in the form.
Fixes#751
* Use dryRun All