Compare commits

..

61 Commits

Author SHA1 Message Date
Zoltán Bedi
8555bcba5b Add tests for migrations 2025-12-11 21:36:38 +01:00
Zoltán Bedi
4c601944e1 Add docs 2025-12-11 21:17:36 +01:00
Zoltán Bedi
a632f1f26a Extract labels 2025-12-11 15:50:53 +01:00
Zoltán Bedi
4d82e4295f Enhance SelectRow component with improved alias option handling
- Updated alias options for time series and variable queries to prevent duplicates and ensure correct options are displayed.
2025-12-10 12:14:54 +01:00
Zoltán Bedi
a91f64b9f5 Refactor response parser and tests for backwards compatibility
- Updated `transformMetricFindResponse` to handle cases without `__text` and `__value` fields, ensuring all values are treated as text-only entries.
- Adjusted test cases to reflect the new behavior and maintain backwards compatibility.
- Enhanced property handling to skip reserved field names when applicable.
2025-12-09 14:25:40 +01:00
Zoltán Bedi
b0e1ff8073 Enhance SQL Query Editor with variable query support
- Added `isVariableQuery` prop to `SqlQueryEditor`, `SelectRow`, and `VisualEditor` components to handle variable queries.
- Updated alias options in `SelectRow` to include variable query specific options.
- Modified `VariableQueryEditor` to set `isVariableQuery` to true when passing props to `SqlQueryEditorLazy`.
2025-12-09 13:19:42 +01:00
Zoltán Bedi
5c455ec2bc Refactor response parser to enhance metric transformation logic
- Updated the `transformMetricFindResponse` function to handle multiple fields more effectively, ensuring all values are included in the output.
- Introduced helper functions for better code organization and readability.
- Adjusted tests to reflect changes in the transformation logic, ensuring accurate validation of properties and deduplication behavior.
2025-12-09 12:05:31 +01:00
Zoltán Bedi
d5215a5be2 PostgreSQL: Add variable query editor support
- Introduced a new feature toggle for the PostgreSQL variable query editor `postgresVariableQueryEditor`.
2025-12-08 23:18:00 +01:00
Bogdan Matei
15c93100ab Dashboards: Fix autogrid selection / drag and drop (#114964)
Some checks failed
Frontend performance tests / performance-tests (push) Has been cancelled
Actionlint / Lint GitHub Actions files (push) Has been cancelled
Backend Code Checks / Detect whether code changed (push) Has been cancelled
Backend Code Checks / Validate Backend Configs (push) Has been cancelled
Backend Unit Tests / Detect whether code changed (push) Has been cancelled
Backend Unit Tests / Grafana (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana (8/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (8/8) (push) Has been cancelled
Backend Unit Tests / All backend unit tests complete (push) Has been cancelled
Lint Frontend / Detect whether code changed (push) Has been cancelled
Lint Frontend / Lint (push) Has been cancelled
Lint Frontend / Typecheck (push) Has been cancelled
Lint Frontend / Verify API clients (push) Has been cancelled
Lint Frontend / Verify API clients (enterprise) (push) Has been cancelled
Verify i18n / verify-i18n (push) Has been cancelled
End-to-end tests / Detect whether code changed (push) Has been cancelled
End-to-end tests / Build & Package Grafana (push) Has been cancelled
End-to-end tests / Build E2E test runner (push) Has been cancelled
End-to-end tests / push-docker-image (push) Has been cancelled
End-to-end tests / dashboards-suite (old arch) (push) Has been cancelled
End-to-end tests / panels-suite (old arch) (push) Has been cancelled
End-to-end tests / smoke-tests-suite (old arch) (push) Has been cancelled
End-to-end tests / various-suite (old arch) (push) Has been cancelled
End-to-end tests / Verify Storybook (Playwright) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (1/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (2/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (3/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (4/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (5/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (6/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (7/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (8/8) (push) Has been cancelled
End-to-end tests / run-azure-monitor-e2e (push) Has been cancelled
End-to-end tests / All Playwright tests complete (push) Has been cancelled
End-to-end tests / A11y test (push) Has been cancelled
End-to-end tests / Publish metrics (push) Has been cancelled
End-to-end tests / All E2E tests complete (push) Has been cancelled
Frontend tests / Detect whether code changed (push) Has been cancelled
Frontend tests / Unit tests (1 / 16) (push) Has been cancelled
Frontend tests / Unit tests (10 / 16) (push) Has been cancelled
Frontend tests / Unit tests (11 / 16) (push) Has been cancelled
Frontend tests / Unit tests (12 / 16) (push) Has been cancelled
Frontend tests / Unit tests (13 / 16) (push) Has been cancelled
Frontend tests / Unit tests (14 / 16) (push) Has been cancelled
Frontend tests / Unit tests (15 / 16) (push) Has been cancelled
Frontend tests / Unit tests (16 / 16) (push) Has been cancelled
Frontend tests / Unit tests (2 / 16) (push) Has been cancelled
Frontend tests / Unit tests (3 / 16) (push) Has been cancelled
Frontend tests / Unit tests (4 / 16) (push) Has been cancelled
Frontend tests / Unit tests (5 / 16) (push) Has been cancelled
Frontend tests / Unit tests (6 / 16) (push) Has been cancelled
Frontend tests / Unit tests (7 / 16) (push) Has been cancelled
Frontend tests / Unit tests (8 / 16) (push) Has been cancelled
Frontend tests / Unit tests (9 / 16) (push) Has been cancelled
Frontend tests / Decoupled plugin tests (push) Has been cancelled
Frontend tests / Packages unit tests (push) Has been cancelled
Frontend tests / All frontend unit tests complete (push) Has been cancelled
Frontend tests / Devenv frontend-service build (push) Has been cancelled
Integration Tests / Detect whether code changed (push) Has been cancelled
Integration Tests / Sqlite (1/4) (push) Has been cancelled
Integration Tests / Sqlite (2/4) (push) Has been cancelled
Integration Tests / Sqlite (3/4) (push) Has been cancelled
Integration Tests / Sqlite (4/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (1/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (2/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (3/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (4/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (profiled) (push) Has been cancelled
Integration Tests / MySQL (1/16) (push) Has been cancelled
Integration Tests / MySQL (10/16) (push) Has been cancelled
Integration Tests / MySQL (11/16) (push) Has been cancelled
Integration Tests / MySQL (12/16) (push) Has been cancelled
Integration Tests / MySQL (13/16) (push) Has been cancelled
Integration Tests / MySQL (14/16) (push) Has been cancelled
Integration Tests / MySQL (15/16) (push) Has been cancelled
Integration Tests / MySQL (16/16) (push) Has been cancelled
Integration Tests / MySQL (2/16) (push) Has been cancelled
Integration Tests / MySQL (3/16) (push) Has been cancelled
Integration Tests / MySQL (4/16) (push) Has been cancelled
Integration Tests / MySQL (5/16) (push) Has been cancelled
Integration Tests / MySQL (6/16) (push) Has been cancelled
Integration Tests / MySQL (7/16) (push) Has been cancelled
Integration Tests / MySQL (8/16) (push) Has been cancelled
Integration Tests / MySQL (9/16) (push) Has been cancelled
Integration Tests / Postgres (1/16) (push) Has been cancelled
Integration Tests / Postgres (10/16) (push) Has been cancelled
Integration Tests / Postgres (11/16) (push) Has been cancelled
Integration Tests / Postgres (12/16) (push) Has been cancelled
Integration Tests / Postgres (13/16) (push) Has been cancelled
Integration Tests / Postgres (14/16) (push) Has been cancelled
Integration Tests / Postgres (15/16) (push) Has been cancelled
Integration Tests / Postgres (16/16) (push) Has been cancelled
Integration Tests / Postgres (2/16) (push) Has been cancelled
Integration Tests / Postgres (3/16) (push) Has been cancelled
Integration Tests / Postgres (4/16) (push) Has been cancelled
Integration Tests / Postgres (5/16) (push) Has been cancelled
Integration Tests / Postgres (6/16) (push) Has been cancelled
Integration Tests / Postgres (7/16) (push) Has been cancelled
Integration Tests / Postgres (8/16) (push) Has been cancelled
Integration Tests / Postgres (9/16) (push) Has been cancelled
Integration Tests / All backend integration tests complete (push) Has been cancelled
Reject GitHub secrets / reject-gh-secrets (push) Has been cancelled
Build Release Packages / setup (push) Has been cancelled
Build Release Packages / Dispatch grafana-enterprise build (push) Has been cancelled
Build Release Packages / / darwin-amd64 (push) Has been cancelled
Build Release Packages / / darwin-arm64 (push) Has been cancelled
Build Release Packages / / linux-amd64 (push) Has been cancelled
Build Release Packages / / linux-armv6 (push) Has been cancelled
Build Release Packages / / linux-armv7 (push) Has been cancelled
Build Release Packages / / linux-arm64 (push) Has been cancelled
Build Release Packages / / linux-s390x (push) Has been cancelled
Build Release Packages / / windows-amd64 (push) Has been cancelled
Build Release Packages / / windows-arm64 (push) Has been cancelled
Build Release Packages / Upload artifacts (push) Has been cancelled
Build Release Packages / publish-dockerhub (push) Has been cancelled
Build Release Packages / Dispatch publish NPM canaries (push) Has been cancelled
Build Release Packages / notify-pr (push) Has been cancelled
Run dashboard schema v2 e2e / dashboard-schema-v2-e2e (push) Has been cancelled
Shellcheck / Shellcheck scripts (push) Has been cancelled
Run Storybook a11y tests / Detect whether code changed (push) Has been cancelled
Run Storybook a11y tests / Run Storybook a11y tests (light theme) (push) Has been cancelled
Run Storybook a11y tests / Run Storybook a11y tests (dark theme) (push) Has been cancelled
Swagger generated code / Detect whether code changed (push) Has been cancelled
Swagger generated code / Verify committed API specs match (push) Has been cancelled
Dispatch sync to mirror / dispatch-job (push) Has been cancelled
CodeQL checks / Detect whether code changed (push) Has been cancelled
CodeQL checks / Analyze (actions) (push) Has been cancelled
CodeQL checks / Analyze (go) (push) Has been cancelled
CodeQL checks / Analyze (javascript) (push) Has been cancelled
golangci-lint / Detect whether code changed (push) Has been cancelled
golangci-lint / go-fmt (push) Has been cancelled
golangci-lint / lint-go (push) Has been cancelled
Crowdin Upload Action / upload-sources-to-crowdin (push) Has been cancelled
publish-kinds-next / main (push) Has been cancelled
trigger-dashboard-search-e2e / trigger-search-e2e (push) Has been cancelled
Relyance Compliance Inspection / relyance-compliance-inspector (push) Has been cancelled
Crowdin Download Action / download-sources-from-crowdin (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled
2025-12-08 16:52:00 +00:00
Sergej-Vlasov
ab9b070eb0 VariablesEditView: Update cloned variable key when duplicating (#114908)
update cloned variable key when duplicating
2025-12-08 16:34:21 +00:00
Tim Levett
e40673b298 github-action: Breaking change label prompts you to create a what's new (#113241)
* (workflow) add in what's new comment when we have a breaking change

* levitate as well

* fix add to what's new label
2025-12-08 16:23:14 +00:00
Victor Marin
7ea009c7f8 Dashboards: Per panel filtering for timeseries (#114499)
* wip per panel group by

* wip groupBy per panel

* wip groupBy per panel

* groupBy per panel action tests

* fix

* fix

* fix

* fix

* CR mods

* switch to dropdown

* adjust apply

* optimise action logic to avoid unnecessary triggers

* canary scenes

* wip

(cherry picked from commit 51a00db93d0805f481a9e48213382468f1eb2986)

* optimise action logic to avoid unnecessary triggers

(cherry picked from commit c4de2dfff8)

* refactor

* refactor

* memoize values/ refactor

* refactor

* refactor components - do not make async call unless queries/groupByOptions change

* canary scenes

* fix test

* Optimise handlers

* Reset options if they are not applied

* refactor subscriptions

* refactor

* scenes bump

* fixes

* properly deactivate header actions on panel edit

* list

* refactor showing menu using css, remove header deactivation code from panel-edit

* cleanup

* cleanup

* cleanup + action redesign

* i18n

* wip

* wip

* wip

* wip

* wip

* tests

* pr mods

* translations

* fix

* fix

* fixes

* translations

* translations

* extra ff check

* CR mods

---------

Co-authored-by: Sergej-Vlasov <sergej.s.vlasov@gmail.com>
Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com>
2025-12-08 16:18:04 +00:00
Kristina Demeshchik
fef6196195 Dashboard: Default weekStart to an empty string (#114932)
* Default clien scene-based logic to empty string to match backend + non-scene logic

* re-gen snapshots
2025-12-08 10:49:36 -05:00
Ashley Harrison
b50cf6e067 FieldColor: Group new accessible options within the select menu (#114690)
* group new accessible options within the select menu

* move comment
2025-12-08 15:10:16 +00:00
Lauren
ccdb6ff261 Alerting: Fix alert instances count display (#114965)
Alerting: fix alert instances count display
2025-12-08 14:54:46 +00:00
Gábor Farkas
692712961b datasources: querier: configurable concurrent-query-limit (#114585) 2025-12-08 15:20:01 +01:00
Mihai Doarna
b2e1b257b3 IAM: Add search for teams in app platform (#113503)
* add legacy search (wip)

* fix search field name

* implement team search endpoint

* generate openapi spec

* generate endpoints for frontend

* minor fixes

* fix issues found while testing

* add more fields to search result

* add basic unit tests

* add more unit tests

* improve getColumns() func in legacy search

* configure search endpoint in team.cue

* add team search handler

* add the searchTeams endpoint to manifest.cue

* make gofmt

* update openapi spec

* generate frontend endpoints

* remove unused field

* move fields defiitions to separate builder

* fix legacy search

* fix unit tests

* fix unit test

* address feedback

* fix unit test

* update openapi specs

* yarn generate-apis

* add missing unit tests
2025-12-08 15:02:59 +02:00
Ashley Harrison
5bd73f3264 Icon: Use empty <svg> as fallback to prevent layout shift (#114901)
render an empty `<svg>` instead to better match styles in other components
2025-12-08 11:11:50 +00:00
Levente Balogh
5a8a730cfe UI Extensions: Add openInNewTab property to link extensions (#114831)
feat: add `openInNewTab` property for link extensions
2025-12-08 12:09:56 +01:00
Hugo Häggmark
7c5457a75e e2e: update @grafana/plugin-e2e version (#114958) 2025-12-08 10:36:34 +00:00
Oscar Kilhed
dab64addf8 SchemaV2: Always set ad hoc filters to empty array when converting to v2 (#114914)
* Always set ad hoc filters to empty array when converting to v2

* Update test files
2025-12-08 11:27:55 +01:00
Ashley Harrison
310662a4d0 QueryEditor: Expose aria-labelledby prop, reenable storybook a11y tests (#114925)
* expose aria-label prop, reenable storybook a11y tests

* extract translations

* expose aria-labelledby instead
2025-12-08 10:27:40 +00:00
Hugo Häggmark
3490c3b0fd e2e: add tests for translations (#114390)
e2e: add tests for translations
2025-12-08 10:19:44 +01:00
Torkel Ödegaard
8bf3ac9710 SelectBase: Use standard portal container (#114844)
Some checks failed
Frontend performance tests / performance-tests (push) Has been cancelled
Actionlint / Lint GitHub Actions files (push) Has been cancelled
Backend Code Checks / Detect whether code changed (push) Has been cancelled
Backend Code Checks / Validate Backend Configs (push) Has been cancelled
Backend Unit Tests / Detect whether code changed (push) Has been cancelled
Backend Unit Tests / Grafana (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana (8/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (8/8) (push) Has been cancelled
Backend Unit Tests / All backend unit tests complete (push) Has been cancelled
CodeQL checks / Detect whether code changed (push) Has been cancelled
CodeQL checks / Analyze (actions) (push) Has been cancelled
CodeQL checks / Analyze (go) (push) Has been cancelled
CodeQL checks / Analyze (javascript) (push) Has been cancelled
Lint Frontend / Detect whether code changed (push) Has been cancelled
Lint Frontend / Lint (push) Has been cancelled
Lint Frontend / Typecheck (push) Has been cancelled
Lint Frontend / Verify API clients (push) Has been cancelled
Lint Frontend / Verify API clients (enterprise) (push) Has been cancelled
golangci-lint / Detect whether code changed (push) Has been cancelled
golangci-lint / go-fmt (push) Has been cancelled
golangci-lint / lint-go (push) Has been cancelled
Verify i18n / verify-i18n (push) Has been cancelled
End-to-end tests / Detect whether code changed (push) Has been cancelled
End-to-end tests / Build & Package Grafana (push) Has been cancelled
End-to-end tests / Build E2E test runner (push) Has been cancelled
End-to-end tests / push-docker-image (push) Has been cancelled
End-to-end tests / dashboards-suite (old arch) (push) Has been cancelled
End-to-end tests / panels-suite (old arch) (push) Has been cancelled
End-to-end tests / smoke-tests-suite (old arch) (push) Has been cancelled
End-to-end tests / various-suite (old arch) (push) Has been cancelled
End-to-end tests / Verify Storybook (Playwright) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (1/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (2/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (3/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (4/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (5/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (6/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (7/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (8/8) (push) Has been cancelled
End-to-end tests / run-azure-monitor-e2e (push) Has been cancelled
End-to-end tests / All Playwright tests complete (push) Has been cancelled
End-to-end tests / A11y test (push) Has been cancelled
End-to-end tests / Publish metrics (push) Has been cancelled
End-to-end tests / All E2E tests complete (push) Has been cancelled
Frontend tests / Detect whether code changed (push) Has been cancelled
Frontend tests / Unit tests (1 / 16) (push) Has been cancelled
Frontend tests / Unit tests (10 / 16) (push) Has been cancelled
Frontend tests / Unit tests (11 / 16) (push) Has been cancelled
Frontend tests / Unit tests (12 / 16) (push) Has been cancelled
Frontend tests / Unit tests (13 / 16) (push) Has been cancelled
Frontend tests / Unit tests (14 / 16) (push) Has been cancelled
Frontend tests / Unit tests (15 / 16) (push) Has been cancelled
Frontend tests / Unit tests (16 / 16) (push) Has been cancelled
Frontend tests / Unit tests (2 / 16) (push) Has been cancelled
Frontend tests / Unit tests (3 / 16) (push) Has been cancelled
Frontend tests / Unit tests (4 / 16) (push) Has been cancelled
Frontend tests / Unit tests (5 / 16) (push) Has been cancelled
Frontend tests / Unit tests (6 / 16) (push) Has been cancelled
Frontend tests / Unit tests (7 / 16) (push) Has been cancelled
Frontend tests / Unit tests (8 / 16) (push) Has been cancelled
Frontend tests / Unit tests (9 / 16) (push) Has been cancelled
Frontend tests / Decoupled plugin tests (push) Has been cancelled
Frontend tests / Packages unit tests (push) Has been cancelled
Frontend tests / All frontend unit tests complete (push) Has been cancelled
Frontend tests / Devenv frontend-service build (push) Has been cancelled
Integration Tests / Detect whether code changed (push) Has been cancelled
Integration Tests / Sqlite (1/4) (push) Has been cancelled
Integration Tests / Sqlite (2/4) (push) Has been cancelled
Integration Tests / Sqlite (3/4) (push) Has been cancelled
Integration Tests / Sqlite (4/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (1/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (2/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (3/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (4/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (profiled) (push) Has been cancelled
Integration Tests / MySQL (1/16) (push) Has been cancelled
Integration Tests / MySQL (10/16) (push) Has been cancelled
Integration Tests / MySQL (11/16) (push) Has been cancelled
Integration Tests / MySQL (12/16) (push) Has been cancelled
Integration Tests / MySQL (13/16) (push) Has been cancelled
Integration Tests / MySQL (14/16) (push) Has been cancelled
Integration Tests / MySQL (15/16) (push) Has been cancelled
Integration Tests / MySQL (16/16) (push) Has been cancelled
Integration Tests / MySQL (2/16) (push) Has been cancelled
Integration Tests / MySQL (3/16) (push) Has been cancelled
Integration Tests / MySQL (4/16) (push) Has been cancelled
Integration Tests / MySQL (5/16) (push) Has been cancelled
Integration Tests / MySQL (6/16) (push) Has been cancelled
Integration Tests / MySQL (7/16) (push) Has been cancelled
Integration Tests / MySQL (8/16) (push) Has been cancelled
Integration Tests / MySQL (9/16) (push) Has been cancelled
Integration Tests / Postgres (1/16) (push) Has been cancelled
Integration Tests / Postgres (10/16) (push) Has been cancelled
Integration Tests / Postgres (11/16) (push) Has been cancelled
Integration Tests / Postgres (12/16) (push) Has been cancelled
Integration Tests / Postgres (13/16) (push) Has been cancelled
Integration Tests / Postgres (14/16) (push) Has been cancelled
Integration Tests / Postgres (15/16) (push) Has been cancelled
Integration Tests / Postgres (16/16) (push) Has been cancelled
Integration Tests / Postgres (2/16) (push) Has been cancelled
Integration Tests / Postgres (3/16) (push) Has been cancelled
Integration Tests / Postgres (4/16) (push) Has been cancelled
Integration Tests / Postgres (5/16) (push) Has been cancelled
Integration Tests / Postgres (6/16) (push) Has been cancelled
Integration Tests / Postgres (7/16) (push) Has been cancelled
Integration Tests / Postgres (8/16) (push) Has been cancelled
Integration Tests / Postgres (9/16) (push) Has been cancelled
Integration Tests / All backend integration tests complete (push) Has been cancelled
Reject GitHub secrets / reject-gh-secrets (push) Has been cancelled
Build Release Packages / setup (push) Has been cancelled
Build Release Packages / Dispatch grafana-enterprise build (push) Has been cancelled
Build Release Packages / / darwin-amd64 (push) Has been cancelled
Build Release Packages / / darwin-arm64 (push) Has been cancelled
Build Release Packages / / linux-amd64 (push) Has been cancelled
Build Release Packages / / linux-armv6 (push) Has been cancelled
Build Release Packages / / linux-armv7 (push) Has been cancelled
Build Release Packages / / linux-arm64 (push) Has been cancelled
Build Release Packages / / linux-s390x (push) Has been cancelled
Build Release Packages / / windows-amd64 (push) Has been cancelled
Build Release Packages / / windows-arm64 (push) Has been cancelled
Build Release Packages / Upload artifacts (push) Has been cancelled
Build Release Packages / publish-dockerhub (push) Has been cancelled
Build Release Packages / Dispatch publish NPM canaries (push) Has been cancelled
Build Release Packages / notify-pr (push) Has been cancelled
Run dashboard schema v2 e2e / dashboard-schema-v2-e2e (push) Has been cancelled
Shellcheck / Shellcheck scripts (push) Has been cancelled
Run Storybook a11y tests / Detect whether code changed (push) Has been cancelled
Run Storybook a11y tests / Run Storybook a11y tests (light theme) (push) Has been cancelled
Run Storybook a11y tests / Run Storybook a11y tests (dark theme) (push) Has been cancelled
Swagger generated code / Detect whether code changed (push) Has been cancelled
Swagger generated code / Verify committed API specs match (push) Has been cancelled
Dispatch sync to mirror / dispatch-job (push) Has been cancelled
* SelectBase: Use standard portal container

* Fixed positioning issue
2025-12-08 10:13:56 +01:00
Gabriel MABILLE
d0977b5245 grafana-iam: Add role apis to the standalone app (#114897) 2025-12-08 09:22:28 +01:00
Ryan McKinley
78b1ae4f27 Search: Fix field selector parsing (#114940)
Some checks failed
Frontend performance tests / performance-tests (push) Has been cancelled
Actionlint / Lint GitHub Actions files (push) Has been cancelled
Backend Code Checks / Detect whether code changed (push) Has been cancelled
Backend Unit Tests / Detect whether code changed (push) Has been cancelled
CodeQL checks / Detect whether code changed (push) Has been cancelled
Lint Frontend / Detect whether code changed (push) Has been cancelled
Lint Frontend / Verify API clients (push) Has been cancelled
Lint Frontend / Verify API clients (enterprise) (push) Has been cancelled
golangci-lint / Detect whether code changed (push) Has been cancelled
Verify i18n / verify-i18n (push) Has been cancelled
End-to-end tests / Detect whether code changed (push) Has been cancelled
Frontend tests / Detect whether code changed (push) Has been cancelled
Integration Tests / Detect whether code changed (push) Has been cancelled
Reject GitHub secrets / reject-gh-secrets (push) Has been cancelled
Build Release Packages / setup (push) Has been cancelled
Run dashboard schema v2 e2e / dashboard-schema-v2-e2e (push) Has been cancelled
Shellcheck / Shellcheck scripts (push) Has been cancelled
Run Storybook a11y tests / Detect whether code changed (push) Has been cancelled
Swagger generated code / Detect whether code changed (push) Has been cancelled
Dispatch sync to mirror / dispatch-job (push) Has been cancelled
trigger-dashboard-search-e2e / trigger-search-e2e (push) Has been cancelled
Trivy Scan / trivy-scan (push) Has been cancelled
Backend Code Checks / Validate Backend Configs (push) Has been cancelled
Backend Unit Tests / Grafana (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana (8/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (8/8) (push) Has been cancelled
Backend Unit Tests / All backend unit tests complete (push) Has been cancelled
CodeQL checks / Analyze (actions) (push) Has been cancelled
CodeQL checks / Analyze (go) (push) Has been cancelled
CodeQL checks / Analyze (javascript) (push) Has been cancelled
Lint Frontend / Lint (push) Has been cancelled
Lint Frontend / Typecheck (push) Has been cancelled
golangci-lint / go-fmt (push) Has been cancelled
golangci-lint / lint-go (push) Has been cancelled
End-to-end tests / Build & Package Grafana (push) Has been cancelled
End-to-end tests / Build E2E test runner (push) Has been cancelled
End-to-end tests / push-docker-image (push) Has been cancelled
End-to-end tests / dashboards-suite (old arch) (push) Has been cancelled
End-to-end tests / panels-suite (old arch) (push) Has been cancelled
End-to-end tests / smoke-tests-suite (old arch) (push) Has been cancelled
End-to-end tests / various-suite (old arch) (push) Has been cancelled
End-to-end tests / Verify Storybook (Playwright) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (1/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (2/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (3/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (4/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (5/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (6/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (7/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (8/8) (push) Has been cancelled
End-to-end tests / run-azure-monitor-e2e (push) Has been cancelled
End-to-end tests / All Playwright tests complete (push) Has been cancelled
End-to-end tests / A11y test (push) Has been cancelled
End-to-end tests / Publish metrics (push) Has been cancelled
End-to-end tests / All E2E tests complete (push) Has been cancelled
Frontend tests / Unit tests (1 / 16) (push) Has been cancelled
Frontend tests / Unit tests (10 / 16) (push) Has been cancelled
Frontend tests / Unit tests (11 / 16) (push) Has been cancelled
Frontend tests / Unit tests (12 / 16) (push) Has been cancelled
Frontend tests / Unit tests (13 / 16) (push) Has been cancelled
Frontend tests / Unit tests (14 / 16) (push) Has been cancelled
Frontend tests / Unit tests (15 / 16) (push) Has been cancelled
Frontend tests / Unit tests (16 / 16) (push) Has been cancelled
Frontend tests / Unit tests (2 / 16) (push) Has been cancelled
Frontend tests / Unit tests (3 / 16) (push) Has been cancelled
Frontend tests / Unit tests (4 / 16) (push) Has been cancelled
Frontend tests / Unit tests (5 / 16) (push) Has been cancelled
Frontend tests / Unit tests (6 / 16) (push) Has been cancelled
Frontend tests / Unit tests (7 / 16) (push) Has been cancelled
Frontend tests / Unit tests (8 / 16) (push) Has been cancelled
Frontend tests / Unit tests (9 / 16) (push) Has been cancelled
Frontend tests / Decoupled plugin tests (push) Has been cancelled
Frontend tests / Packages unit tests (push) Has been cancelled
Frontend tests / All frontend unit tests complete (push) Has been cancelled
Frontend tests / Devenv frontend-service build (push) Has been cancelled
Integration Tests / Sqlite (1/4) (push) Has been cancelled
Integration Tests / Sqlite (2/4) (push) Has been cancelled
Integration Tests / Sqlite (3/4) (push) Has been cancelled
Integration Tests / Sqlite (4/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (1/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (2/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (3/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (4/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (profiled) (push) Has been cancelled
Integration Tests / MySQL (1/16) (push) Has been cancelled
Integration Tests / MySQL (10/16) (push) Has been cancelled
Integration Tests / MySQL (11/16) (push) Has been cancelled
Integration Tests / MySQL (12/16) (push) Has been cancelled
Integration Tests / MySQL (13/16) (push) Has been cancelled
Integration Tests / MySQL (14/16) (push) Has been cancelled
Integration Tests / MySQL (15/16) (push) Has been cancelled
Integration Tests / MySQL (16/16) (push) Has been cancelled
Integration Tests / MySQL (2/16) (push) Has been cancelled
Integration Tests / MySQL (3/16) (push) Has been cancelled
Integration Tests / MySQL (4/16) (push) Has been cancelled
Integration Tests / MySQL (5/16) (push) Has been cancelled
Integration Tests / MySQL (6/16) (push) Has been cancelled
Integration Tests / MySQL (7/16) (push) Has been cancelled
Integration Tests / MySQL (8/16) (push) Has been cancelled
Integration Tests / MySQL (9/16) (push) Has been cancelled
Integration Tests / Postgres (1/16) (push) Has been cancelled
Integration Tests / Postgres (10/16) (push) Has been cancelled
Integration Tests / Postgres (11/16) (push) Has been cancelled
Integration Tests / Postgres (12/16) (push) Has been cancelled
Integration Tests / Postgres (13/16) (push) Has been cancelled
Integration Tests / Postgres (14/16) (push) Has been cancelled
Integration Tests / Postgres (15/16) (push) Has been cancelled
Integration Tests / Postgres (16/16) (push) Has been cancelled
Integration Tests / Postgres (2/16) (push) Has been cancelled
Integration Tests / Postgres (3/16) (push) Has been cancelled
Integration Tests / Postgres (4/16) (push) Has been cancelled
Integration Tests / Postgres (5/16) (push) Has been cancelled
Integration Tests / Postgres (6/16) (push) Has been cancelled
Integration Tests / Postgres (7/16) (push) Has been cancelled
Integration Tests / Postgres (8/16) (push) Has been cancelled
Integration Tests / Postgres (9/16) (push) Has been cancelled
Integration Tests / All backend integration tests complete (push) Has been cancelled
Build Release Packages / Dispatch grafana-enterprise build (push) Has been cancelled
Build Release Packages / / darwin-amd64 (push) Has been cancelled
Build Release Packages / / darwin-arm64 (push) Has been cancelled
Build Release Packages / / linux-amd64 (push) Has been cancelled
Build Release Packages / / linux-armv6 (push) Has been cancelled
Build Release Packages / / linux-armv7 (push) Has been cancelled
Build Release Packages / / linux-arm64 (push) Has been cancelled
Build Release Packages / / linux-s390x (push) Has been cancelled
Build Release Packages / / windows-amd64 (push) Has been cancelled
Build Release Packages / / windows-arm64 (push) Has been cancelled
Build Release Packages / Upload artifacts (push) Has been cancelled
Build Release Packages / publish-dockerhub (push) Has been cancelled
Build Release Packages / Dispatch publish NPM canaries (push) Has been cancelled
Build Release Packages / notify-pr (push) Has been cancelled
Run Storybook a11y tests / Run Storybook a11y tests (light theme) (push) Has been cancelled
Run Storybook a11y tests / Run Storybook a11y tests (dark theme) (push) Has been cancelled
Swagger generated code / Verify committed API specs match (push) Has been cancelled
Relyance Compliance Inspection / relyance-compliance-inspector (push) Has been cancelled
Crowdin Download Action / download-sources-from-crowdin (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled
/ Alerting Swagger spec generation cron job (push) Has been cancelled
Update `make docs` procedure / main (push) Has been cancelled
Clean up orphaned branches / cleanup-branches (push) Has been cancelled
2025-12-06 16:45:18 +03:00
Steve Simpson
592c599ca6 Alerting: Add configurable transport to historian app (#114935) 2025-12-06 10:37:20 +01:00
Austin Pond
8e11851bb0 Dashboards: Use the OpenAPI generated by app-sdk in the manifest to … (#114858) 2025-12-06 08:01:28 +00:00
Steve Simpson
e9ba45ca4f Update grafana-app-sdk to v0.48.5 (#114810)
Co-authored-by: Owen Smallwood <owen.smallwood@grafana.com>
Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
2025-12-06 07:34:18 +00:00
grafana-pr-automation[bot]
0f9d0317dc I18n: Download translations from Crowdin (#114938)
Some checks failed
Frontend performance tests / performance-tests (push) Has been cancelled
Actionlint / Lint GitHub Actions files (push) Has been cancelled
Backend Code Checks / Detect whether code changed (push) Has been cancelled
Backend Code Checks / Validate Backend Configs (push) Has been cancelled
Backend Unit Tests / Detect whether code changed (push) Has been cancelled
Backend Unit Tests / Grafana (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana (8/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (8/8) (push) Has been cancelled
Backend Unit Tests / All backend unit tests complete (push) Has been cancelled
CodeQL checks / Detect whether code changed (push) Has been cancelled
CodeQL checks / Analyze (actions) (push) Has been cancelled
CodeQL checks / Analyze (go) (push) Has been cancelled
CodeQL checks / Analyze (javascript) (push) Has been cancelled
Lint Frontend / Detect whether code changed (push) Has been cancelled
Lint Frontend / Lint (push) Has been cancelled
Lint Frontend / Typecheck (push) Has been cancelled
Lint Frontend / Verify API clients (push) Has been cancelled
Lint Frontend / Verify API clients (enterprise) (push) Has been cancelled
golangci-lint / Detect whether code changed (push) Has been cancelled
golangci-lint / go-fmt (push) Has been cancelled
golangci-lint / lint-go (push) Has been cancelled
Verify i18n / verify-i18n (push) Has been cancelled
End-to-end tests / Detect whether code changed (push) Has been cancelled
End-to-end tests / Build & Package Grafana (push) Has been cancelled
End-to-end tests / Build E2E test runner (push) Has been cancelled
End-to-end tests / push-docker-image (push) Has been cancelled
End-to-end tests / dashboards-suite (old arch) (push) Has been cancelled
End-to-end tests / panels-suite (old arch) (push) Has been cancelled
End-to-end tests / smoke-tests-suite (old arch) (push) Has been cancelled
End-to-end tests / various-suite (old arch) (push) Has been cancelled
End-to-end tests / Verify Storybook (Playwright) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (1/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (2/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (3/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (4/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (5/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (6/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (7/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (8/8) (push) Has been cancelled
End-to-end tests / run-azure-monitor-e2e (push) Has been cancelled
End-to-end tests / All Playwright tests complete (push) Has been cancelled
End-to-end tests / A11y test (push) Has been cancelled
End-to-end tests / Publish metrics (push) Has been cancelled
End-to-end tests / All E2E tests complete (push) Has been cancelled
Frontend tests / Detect whether code changed (push) Has been cancelled
Frontend tests / Unit tests (1 / 16) (push) Has been cancelled
Frontend tests / Unit tests (10 / 16) (push) Has been cancelled
Frontend tests / Unit tests (11 / 16) (push) Has been cancelled
Frontend tests / Unit tests (12 / 16) (push) Has been cancelled
Frontend tests / Unit tests (13 / 16) (push) Has been cancelled
Frontend tests / Unit tests (14 / 16) (push) Has been cancelled
Frontend tests / Unit tests (15 / 16) (push) Has been cancelled
Frontend tests / Unit tests (16 / 16) (push) Has been cancelled
Frontend tests / Unit tests (2 / 16) (push) Has been cancelled
Frontend tests / Unit tests (3 / 16) (push) Has been cancelled
Frontend tests / Unit tests (4 / 16) (push) Has been cancelled
Frontend tests / Unit tests (5 / 16) (push) Has been cancelled
Frontend tests / Unit tests (6 / 16) (push) Has been cancelled
Frontend tests / Unit tests (7 / 16) (push) Has been cancelled
Frontend tests / Unit tests (8 / 16) (push) Has been cancelled
Frontend tests / Unit tests (9 / 16) (push) Has been cancelled
Frontend tests / Decoupled plugin tests (push) Has been cancelled
Frontend tests / Packages unit tests (push) Has been cancelled
Frontend tests / All frontend unit tests complete (push) Has been cancelled
Frontend tests / Devenv frontend-service build (push) Has been cancelled
Integration Tests / Detect whether code changed (push) Has been cancelled
Integration Tests / Sqlite (1/4) (push) Has been cancelled
Integration Tests / Sqlite (2/4) (push) Has been cancelled
Integration Tests / Sqlite (3/4) (push) Has been cancelled
Integration Tests / Sqlite (4/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (1/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (2/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (3/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (4/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (profiled) (push) Has been cancelled
Integration Tests / MySQL (1/16) (push) Has been cancelled
Integration Tests / MySQL (10/16) (push) Has been cancelled
Integration Tests / MySQL (11/16) (push) Has been cancelled
Integration Tests / MySQL (12/16) (push) Has been cancelled
Integration Tests / MySQL (13/16) (push) Has been cancelled
Integration Tests / MySQL (14/16) (push) Has been cancelled
Integration Tests / MySQL (15/16) (push) Has been cancelled
Integration Tests / MySQL (16/16) (push) Has been cancelled
Integration Tests / MySQL (2/16) (push) Has been cancelled
Integration Tests / MySQL (3/16) (push) Has been cancelled
Integration Tests / MySQL (4/16) (push) Has been cancelled
Integration Tests / MySQL (5/16) (push) Has been cancelled
Integration Tests / MySQL (6/16) (push) Has been cancelled
Integration Tests / MySQL (7/16) (push) Has been cancelled
Integration Tests / MySQL (8/16) (push) Has been cancelled
Integration Tests / MySQL (9/16) (push) Has been cancelled
Integration Tests / Postgres (1/16) (push) Has been cancelled
Integration Tests / Postgres (10/16) (push) Has been cancelled
Integration Tests / Postgres (11/16) (push) Has been cancelled
Integration Tests / Postgres (12/16) (push) Has been cancelled
Integration Tests / Postgres (13/16) (push) Has been cancelled
Integration Tests / Postgres (14/16) (push) Has been cancelled
Integration Tests / Postgres (15/16) (push) Has been cancelled
Integration Tests / Postgres (16/16) (push) Has been cancelled
Integration Tests / Postgres (2/16) (push) Has been cancelled
Integration Tests / Postgres (3/16) (push) Has been cancelled
Integration Tests / Postgres (4/16) (push) Has been cancelled
Integration Tests / Postgres (5/16) (push) Has been cancelled
Integration Tests / Postgres (6/16) (push) Has been cancelled
Integration Tests / Postgres (7/16) (push) Has been cancelled
Integration Tests / Postgres (8/16) (push) Has been cancelled
Integration Tests / Postgres (9/16) (push) Has been cancelled
Integration Tests / All backend integration tests complete (push) Has been cancelled
Reject GitHub secrets / reject-gh-secrets (push) Has been cancelled
Build Release Packages / setup (push) Has been cancelled
Build Release Packages / Dispatch grafana-enterprise build (push) Has been cancelled
Build Release Packages / / darwin-amd64 (push) Has been cancelled
Build Release Packages / / darwin-arm64 (push) Has been cancelled
Build Release Packages / / linux-amd64 (push) Has been cancelled
Build Release Packages / / linux-armv6 (push) Has been cancelled
Build Release Packages / / linux-armv7 (push) Has been cancelled
Build Release Packages / / linux-arm64 (push) Has been cancelled
Build Release Packages / / linux-s390x (push) Has been cancelled
Build Release Packages / / windows-amd64 (push) Has been cancelled
Build Release Packages / / windows-arm64 (push) Has been cancelled
Build Release Packages / Upload artifacts (push) Has been cancelled
Build Release Packages / publish-dockerhub (push) Has been cancelled
Build Release Packages / Dispatch publish NPM canaries (push) Has been cancelled
Build Release Packages / notify-pr (push) Has been cancelled
Run dashboard schema v2 e2e / dashboard-schema-v2-e2e (push) Has been cancelled
Shellcheck / Shellcheck scripts (push) Has been cancelled
Run Storybook a11y tests / Detect whether code changed (push) Has been cancelled
Run Storybook a11y tests / Run Storybook a11y tests (light theme) (push) Has been cancelled
Run Storybook a11y tests / Run Storybook a11y tests (dark theme) (push) Has been cancelled
Swagger generated code / Detect whether code changed (push) Has been cancelled
Swagger generated code / Verify committed API specs match (push) Has been cancelled
Dispatch sync to mirror / dispatch-job (push) Has been cancelled
New Crowdin translations by GitHub Action

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-12-06 00:40:23 +00:00
Charandas
d1cbef9157 K8s: use runtime config for API Builders (#114601)
* Reapply "K8s: read resource configs from API Enablement for API Builders" (#114475)

This reverts commit 4130bd9cd3.

* revert part that broke things

* FF service changes are gonna come later
2025-12-05 11:53:31 -08:00
Todd Treece
5b89d3b807 Plugins App: Add access control (#114869)
Some checks failed
Frontend performance tests / performance-tests (push) Has been cancelled
Actionlint / Lint GitHub Actions files (push) Has been cancelled
Backend Code Checks / Detect whether code changed (push) Has been cancelled
Backend Code Checks / Validate Backend Configs (push) Has been cancelled
Backend Unit Tests / Detect whether code changed (push) Has been cancelled
Backend Unit Tests / Grafana (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana (8/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (8/8) (push) Has been cancelled
Backend Unit Tests / All backend unit tests complete (push) Has been cancelled
CodeQL checks / Detect whether code changed (push) Has been cancelled
CodeQL checks / Analyze (actions) (push) Has been cancelled
CodeQL checks / Analyze (go) (push) Has been cancelled
CodeQL checks / Analyze (javascript) (push) Has been cancelled
Lint Frontend / Detect whether code changed (push) Has been cancelled
Lint Frontend / Lint (push) Has been cancelled
Lint Frontend / Typecheck (push) Has been cancelled
Lint Frontend / Verify API clients (push) Has been cancelled
Lint Frontend / Verify API clients (enterprise) (push) Has been cancelled
golangci-lint / Detect whether code changed (push) Has been cancelled
golangci-lint / go-fmt (push) Has been cancelled
golangci-lint / lint-go (push) Has been cancelled
Verify i18n / verify-i18n (push) Has been cancelled
End-to-end tests / Detect whether code changed (push) Has been cancelled
End-to-end tests / Build & Package Grafana (push) Has been cancelled
End-to-end tests / Build E2E test runner (push) Has been cancelled
End-to-end tests / push-docker-image (push) Has been cancelled
End-to-end tests / dashboards-suite (old arch) (push) Has been cancelled
End-to-end tests / panels-suite (old arch) (push) Has been cancelled
End-to-end tests / smoke-tests-suite (old arch) (push) Has been cancelled
End-to-end tests / various-suite (old arch) (push) Has been cancelled
End-to-end tests / Verify Storybook (Playwright) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (1/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (2/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (3/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (4/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (5/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (6/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (7/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (8/8) (push) Has been cancelled
End-to-end tests / run-azure-monitor-e2e (push) Has been cancelled
End-to-end tests / All Playwright tests complete (push) Has been cancelled
End-to-end tests / A11y test (push) Has been cancelled
End-to-end tests / Publish metrics (push) Has been cancelled
End-to-end tests / All E2E tests complete (push) Has been cancelled
Frontend tests / Detect whether code changed (push) Has been cancelled
Frontend tests / Unit tests (1 / 16) (push) Has been cancelled
Frontend tests / Unit tests (10 / 16) (push) Has been cancelled
Frontend tests / Unit tests (11 / 16) (push) Has been cancelled
Frontend tests / Unit tests (12 / 16) (push) Has been cancelled
Frontend tests / Unit tests (13 / 16) (push) Has been cancelled
Frontend tests / Unit tests (14 / 16) (push) Has been cancelled
Frontend tests / Unit tests (15 / 16) (push) Has been cancelled
Frontend tests / Unit tests (16 / 16) (push) Has been cancelled
Frontend tests / Unit tests (2 / 16) (push) Has been cancelled
Frontend tests / Unit tests (3 / 16) (push) Has been cancelled
Frontend tests / Unit tests (4 / 16) (push) Has been cancelled
Frontend tests / Unit tests (5 / 16) (push) Has been cancelled
Frontend tests / Unit tests (6 / 16) (push) Has been cancelled
Frontend tests / Unit tests (7 / 16) (push) Has been cancelled
Frontend tests / Unit tests (8 / 16) (push) Has been cancelled
Frontend tests / Unit tests (9 / 16) (push) Has been cancelled
Frontend tests / Decoupled plugin tests (push) Has been cancelled
Frontend tests / Packages unit tests (push) Has been cancelled
Frontend tests / All frontend unit tests complete (push) Has been cancelled
Frontend tests / Devenv frontend-service build (push) Has been cancelled
Integration Tests / Detect whether code changed (push) Has been cancelled
Integration Tests / Sqlite (1/4) (push) Has been cancelled
Integration Tests / Sqlite (2/4) (push) Has been cancelled
Integration Tests / Sqlite (3/4) (push) Has been cancelled
Integration Tests / Sqlite (4/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (1/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (2/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (3/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (4/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (profiled) (push) Has been cancelled
Integration Tests / MySQL (1/16) (push) Has been cancelled
Integration Tests / MySQL (10/16) (push) Has been cancelled
Integration Tests / MySQL (11/16) (push) Has been cancelled
Integration Tests / MySQL (12/16) (push) Has been cancelled
Integration Tests / MySQL (13/16) (push) Has been cancelled
Integration Tests / MySQL (14/16) (push) Has been cancelled
Integration Tests / MySQL (15/16) (push) Has been cancelled
Integration Tests / MySQL (16/16) (push) Has been cancelled
Integration Tests / MySQL (2/16) (push) Has been cancelled
Integration Tests / MySQL (3/16) (push) Has been cancelled
Integration Tests / MySQL (4/16) (push) Has been cancelled
Integration Tests / MySQL (5/16) (push) Has been cancelled
Integration Tests / MySQL (6/16) (push) Has been cancelled
Integration Tests / MySQL (7/16) (push) Has been cancelled
Integration Tests / MySQL (8/16) (push) Has been cancelled
Integration Tests / MySQL (9/16) (push) Has been cancelled
Integration Tests / Postgres (1/16) (push) Has been cancelled
Integration Tests / Postgres (10/16) (push) Has been cancelled
Integration Tests / Postgres (11/16) (push) Has been cancelled
Integration Tests / Postgres (12/16) (push) Has been cancelled
Integration Tests / Postgres (13/16) (push) Has been cancelled
Integration Tests / Postgres (14/16) (push) Has been cancelled
Integration Tests / Postgres (15/16) (push) Has been cancelled
Integration Tests / Postgres (16/16) (push) Has been cancelled
Integration Tests / Postgres (2/16) (push) Has been cancelled
Integration Tests / Postgres (3/16) (push) Has been cancelled
Integration Tests / Postgres (4/16) (push) Has been cancelled
Integration Tests / Postgres (5/16) (push) Has been cancelled
Integration Tests / Postgres (6/16) (push) Has been cancelled
Integration Tests / Postgres (7/16) (push) Has been cancelled
Integration Tests / Postgres (8/16) (push) Has been cancelled
Integration Tests / Postgres (9/16) (push) Has been cancelled
Integration Tests / All backend integration tests complete (push) Has been cancelled
Reject GitHub secrets / reject-gh-secrets (push) Has been cancelled
Build Release Packages / setup (push) Has been cancelled
Build Release Packages / Dispatch grafana-enterprise build (push) Has been cancelled
Build Release Packages / / darwin-amd64 (push) Has been cancelled
Build Release Packages / / darwin-arm64 (push) Has been cancelled
Build Release Packages / / linux-amd64 (push) Has been cancelled
Build Release Packages / / linux-armv6 (push) Has been cancelled
Build Release Packages / / linux-armv7 (push) Has been cancelled
Build Release Packages / / linux-arm64 (push) Has been cancelled
Build Release Packages / / linux-s390x (push) Has been cancelled
Build Release Packages / / windows-amd64 (push) Has been cancelled
Build Release Packages / / windows-arm64 (push) Has been cancelled
Build Release Packages / Upload artifacts (push) Has been cancelled
Build Release Packages / publish-dockerhub (push) Has been cancelled
Build Release Packages / Dispatch publish NPM canaries (push) Has been cancelled
Build Release Packages / notify-pr (push) Has been cancelled
Run dashboard schema v2 e2e / dashboard-schema-v2-e2e (push) Has been cancelled
Shellcheck / Shellcheck scripts (push) Has been cancelled
Run Storybook a11y tests / Detect whether code changed (push) Has been cancelled
Run Storybook a11y tests / Run Storybook a11y tests (light theme) (push) Has been cancelled
Run Storybook a11y tests / Run Storybook a11y tests (dark theme) (push) Has been cancelled
Swagger generated code / Detect whether code changed (push) Has been cancelled
Swagger generated code / Verify committed API specs match (push) Has been cancelled
Dispatch sync to mirror / dispatch-job (push) Has been cancelled
Crowdin Upload Action / upload-sources-to-crowdin (push) Has been cancelled
Documentation / Build & Verify Docs (push) Has been cancelled
publish-kinds-next / main (push) Has been cancelled
publish-technical-documentation-next / sync (push) Has been cancelled
Relyance Compliance Inspection / relyance-compliance-inspector (push) Has been cancelled
Crowdin Download Action / download-sources-from-crowdin (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled
2025-12-05 12:56:01 -05:00
Alexander Akhmetov
74c7b5a292 Alerting: Fix creating a new alert rule vesion when only keep_firing_for changes (#114926)
Alerting: Create alert rule vesion when keep_firing_for changes
2025-12-05 18:02:11 +01:00
Marc M.
0adb2461e9 Dashboards: Improve custom variable editor and undo/redo (#114559) 2025-12-05 16:48:34 +01:00
Sarah Zinger
7cd10aa49e SQL Expressions: Fix alerts with sql expressions that have a cte (#114852)
Fix for #114377 - fix alerts with sql expressions that have a cte
2025-12-05 10:14:02 -05:00
Bogdan Matei
bf042afa98 Dashboard: Fix dropping panels in tabs and rows (#114893) 2025-12-05 17:12:12 +02:00
Santiago
b19e546254 Remote Alertmanager: Remove X-Remote-Alertmanager header (#114917)
Remote Alertmanager: Remove X-Remote-Alertmanager haeder
2025-12-05 15:04:42 +00:00
Ryan McKinley
5ac702a4c1 Dashboards: update manifest to avoid useoldmanifestkinds (#114910) 2025-12-05 16:21:30 +02:00
Alexander Zobnin
8a0fa93aec Zanzana: Fix duplicated writes in one request (#114900)
* Zanzana: Fix duplicated writes

* add tests
2025-12-05 13:55:56 +01:00
Tung Nguyen
65817794b5 OpenTSDB: Remove gf-form from opentsdb Annotation Editor (#112590)
* Chore: Remove gf-form in opentsdb AnnotationEditor

* Fix: small typo

* chore: remove stale eslint suppression rule
2025-12-05 12:26:56 +00:00
Andreas Christou
b719aea078 Azure: Fix dcount aggregation (#114666)
* Add parameter type field

* Use parameterType to filter columns for aggregation funcs

* Support selecting column for dcount aggregation
2025-12-05 12:25:56 +00:00
Ryan McKinley
75eb820c73 Folders: update manifest (avoid useoldmanifestkinds) (#114827) 2025-12-05 15:01:11 +03:00
Sergej-Vlasov
be99781176 TransformSaveModelToScene: Force v1 for reports (#114767)
force v1 for reports
2025-12-05 11:01:43 +00:00
Andreas Christou
0a51779107 MSSQL: Remove the need for azure_auth_enabled (#114775)
Remove the need for azure_auth_enabled for MSSQL
2025-12-05 10:42:17 +00:00
Torkel Ödegaard
c74af430a6 Gauge: Only show spotlight in dark themes (#114524)
Some checks failed
Frontend performance tests / performance-tests (push) Has been cancelled
Actionlint / Lint GitHub Actions files (push) Has been cancelled
Backend Code Checks / Detect whether code changed (push) Has been cancelled
Backend Code Checks / Validate Backend Configs (push) Has been cancelled
Backend Unit Tests / Detect whether code changed (push) Has been cancelled
Backend Unit Tests / Grafana (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana (8/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (8/8) (push) Has been cancelled
Backend Unit Tests / All backend unit tests complete (push) Has been cancelled
CodeQL checks / Detect whether code changed (push) Has been cancelled
CodeQL checks / Analyze (actions) (push) Has been cancelled
CodeQL checks / Analyze (go) (push) Has been cancelled
CodeQL checks / Analyze (javascript) (push) Has been cancelled
Lint Frontend / Detect whether code changed (push) Has been cancelled
Lint Frontend / Lint (push) Has been cancelled
Lint Frontend / Typecheck (push) Has been cancelled
Lint Frontend / Verify API clients (push) Has been cancelled
Lint Frontend / Verify API clients (enterprise) (push) Has been cancelled
golangci-lint / Detect whether code changed (push) Has been cancelled
golangci-lint / go-fmt (push) Has been cancelled
golangci-lint / lint-go (push) Has been cancelled
Crowdin Upload Action / upload-sources-to-crowdin (push) Has been cancelled
Verify i18n / verify-i18n (push) Has been cancelled
Documentation / Build & Verify Docs (push) Has been cancelled
End-to-end tests / Detect whether code changed (push) Has been cancelled
End-to-end tests / Build & Package Grafana (push) Has been cancelled
End-to-end tests / Build E2E test runner (push) Has been cancelled
End-to-end tests / push-docker-image (push) Has been cancelled
End-to-end tests / dashboards-suite (old arch) (push) Has been cancelled
End-to-end tests / panels-suite (old arch) (push) Has been cancelled
End-to-end tests / smoke-tests-suite (old arch) (push) Has been cancelled
End-to-end tests / various-suite (old arch) (push) Has been cancelled
End-to-end tests / Verify Storybook (Playwright) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (1/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (2/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (3/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (4/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (5/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (6/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (7/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (8/8) (push) Has been cancelled
End-to-end tests / run-azure-monitor-e2e (push) Has been cancelled
End-to-end tests / All Playwright tests complete (push) Has been cancelled
End-to-end tests / A11y test (push) Has been cancelled
End-to-end tests / Publish metrics (push) Has been cancelled
End-to-end tests / All E2E tests complete (push) Has been cancelled
Frontend tests / Detect whether code changed (push) Has been cancelled
Frontend tests / Unit tests (1 / 16) (push) Has been cancelled
Frontend tests / Unit tests (10 / 16) (push) Has been cancelled
Frontend tests / Unit tests (11 / 16) (push) Has been cancelled
Frontend tests / Unit tests (12 / 16) (push) Has been cancelled
Frontend tests / Unit tests (13 / 16) (push) Has been cancelled
Frontend tests / Unit tests (14 / 16) (push) Has been cancelled
Frontend tests / Unit tests (15 / 16) (push) Has been cancelled
Frontend tests / Unit tests (16 / 16) (push) Has been cancelled
Frontend tests / Unit tests (2 / 16) (push) Has been cancelled
Frontend tests / Unit tests (3 / 16) (push) Has been cancelled
Frontend tests / Unit tests (4 / 16) (push) Has been cancelled
Frontend tests / Unit tests (5 / 16) (push) Has been cancelled
Frontend tests / Unit tests (6 / 16) (push) Has been cancelled
Frontend tests / Unit tests (7 / 16) (push) Has been cancelled
Frontend tests / Unit tests (8 / 16) (push) Has been cancelled
Frontend tests / Unit tests (9 / 16) (push) Has been cancelled
Frontend tests / Decoupled plugin tests (push) Has been cancelled
Frontend tests / Packages unit tests (push) Has been cancelled
Frontend tests / All frontend unit tests complete (push) Has been cancelled
Frontend tests / Devenv frontend-service build (push) Has been cancelled
Integration Tests / Detect whether code changed (push) Has been cancelled
Integration Tests / Sqlite (1/4) (push) Has been cancelled
Integration Tests / Sqlite (2/4) (push) Has been cancelled
Integration Tests / Sqlite (3/4) (push) Has been cancelled
Integration Tests / Sqlite (4/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (1/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (2/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (3/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (4/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (profiled) (push) Has been cancelled
Integration Tests / MySQL (1/16) (push) Has been cancelled
Integration Tests / MySQL (10/16) (push) Has been cancelled
Integration Tests / MySQL (11/16) (push) Has been cancelled
Integration Tests / MySQL (12/16) (push) Has been cancelled
Integration Tests / MySQL (13/16) (push) Has been cancelled
Integration Tests / MySQL (14/16) (push) Has been cancelled
Integration Tests / MySQL (15/16) (push) Has been cancelled
Integration Tests / MySQL (16/16) (push) Has been cancelled
Integration Tests / MySQL (2/16) (push) Has been cancelled
Integration Tests / MySQL (3/16) (push) Has been cancelled
Integration Tests / MySQL (4/16) (push) Has been cancelled
Integration Tests / MySQL (5/16) (push) Has been cancelled
Integration Tests / MySQL (6/16) (push) Has been cancelled
Integration Tests / MySQL (7/16) (push) Has been cancelled
Integration Tests / MySQL (8/16) (push) Has been cancelled
Integration Tests / MySQL (9/16) (push) Has been cancelled
Integration Tests / Postgres (1/16) (push) Has been cancelled
Integration Tests / Postgres (10/16) (push) Has been cancelled
Integration Tests / Postgres (11/16) (push) Has been cancelled
Integration Tests / Postgres (12/16) (push) Has been cancelled
Integration Tests / Postgres (13/16) (push) Has been cancelled
Integration Tests / Postgres (14/16) (push) Has been cancelled
Integration Tests / Postgres (15/16) (push) Has been cancelled
Integration Tests / Postgres (16/16) (push) Has been cancelled
Integration Tests / Postgres (2/16) (push) Has been cancelled
Integration Tests / Postgres (3/16) (push) Has been cancelled
Integration Tests / Postgres (4/16) (push) Has been cancelled
Integration Tests / Postgres (5/16) (push) Has been cancelled
Integration Tests / Postgres (6/16) (push) Has been cancelled
Integration Tests / Postgres (7/16) (push) Has been cancelled
Integration Tests / Postgres (8/16) (push) Has been cancelled
Integration Tests / Postgres (9/16) (push) Has been cancelled
Integration Tests / All backend integration tests complete (push) Has been cancelled
publish-technical-documentation-next / sync (push) Has been cancelled
Reject GitHub secrets / reject-gh-secrets (push) Has been cancelled
Build Release Packages / setup (push) Has been cancelled
Build Release Packages / Dispatch grafana-enterprise build (push) Has been cancelled
Build Release Packages / / darwin-amd64 (push) Has been cancelled
Build Release Packages / / darwin-arm64 (push) Has been cancelled
Build Release Packages / / linux-amd64 (push) Has been cancelled
Build Release Packages / / linux-armv6 (push) Has been cancelled
Build Release Packages / / linux-armv7 (push) Has been cancelled
Build Release Packages / / linux-arm64 (push) Has been cancelled
Build Release Packages / / linux-s390x (push) Has been cancelled
Build Release Packages / / windows-amd64 (push) Has been cancelled
Build Release Packages / / windows-arm64 (push) Has been cancelled
Build Release Packages / Upload artifacts (push) Has been cancelled
Build Release Packages / publish-dockerhub (push) Has been cancelled
Build Release Packages / Dispatch publish NPM canaries (push) Has been cancelled
Build Release Packages / notify-pr (push) Has been cancelled
Run dashboard schema v2 e2e / dashboard-schema-v2-e2e (push) Has been cancelled
Shellcheck / Shellcheck scripts (push) Has been cancelled
Run Storybook a11y tests / Detect whether code changed (push) Has been cancelled
Run Storybook a11y tests / Run Storybook a11y tests (light theme) (push) Has been cancelled
Run Storybook a11y tests / Run Storybook a11y tests (dark theme) (push) Has been cancelled
Swagger generated code / Detect whether code changed (push) Has been cancelled
Swagger generated code / Verify committed API specs match (push) Has been cancelled
Dispatch sync to mirror / dispatch-job (push) Has been cancelled
* Gauge: Only show spotlight in dark themes

* Update
2025-12-05 08:48:39 +01:00
Hugo Häggmark
88478a851e chore: reduce Loki barrel files (#114888) 2025-12-05 08:29:48 +01:00
Pepe Cano
a8d174ccef docs(alerting): add new Examples of trace-based alerts (#114511)
* docs(alerting): add new Examples of trace-based alerts

* fix vale issues
2025-12-05 08:28:16 +01:00
Hugo Häggmark
b3648f0823 chore: introduce toggle for decoupling plugins from bootdata (#114890)
chore: toggle for decoupling plugins from bootdata
2025-12-05 08:09:41 +01:00
grafana-pr-automation[bot]
c53500378e I18n: Download translations from Crowdin (#114886)
New Crowdin translations by GitHub Action

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-12-05 00:48:25 +00:00
Galen Kistler
10ad94af38 TableRT: fix bug preventing users from selecting filter operators (#114860)
Some checks failed
Frontend performance tests / performance-tests (push) Has been cancelled
Actionlint / Lint GitHub Actions files (push) Has been cancelled
Backend Code Checks / Detect whether code changed (push) Has been cancelled
Backend Code Checks / Validate Backend Configs (push) Has been cancelled
Backend Unit Tests / Detect whether code changed (push) Has been cancelled
Backend Unit Tests / Grafana (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana (8/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (8/8) (push) Has been cancelled
Backend Unit Tests / All backend unit tests complete (push) Has been cancelled
CodeQL checks / Detect whether code changed (push) Has been cancelled
CodeQL checks / Analyze (actions) (push) Has been cancelled
CodeQL checks / Analyze (go) (push) Has been cancelled
CodeQL checks / Analyze (javascript) (push) Has been cancelled
Lint Frontend / Detect whether code changed (push) Has been cancelled
Lint Frontend / Lint (push) Has been cancelled
Lint Frontend / Typecheck (push) Has been cancelled
Lint Frontend / Verify API clients (push) Has been cancelled
Lint Frontend / Verify API clients (enterprise) (push) Has been cancelled
golangci-lint / Detect whether code changed (push) Has been cancelled
golangci-lint / go-fmt (push) Has been cancelled
golangci-lint / lint-go (push) Has been cancelled
Crowdin Upload Action / upload-sources-to-crowdin (push) Has been cancelled
Verify i18n / verify-i18n (push) Has been cancelled
End-to-end tests / Detect whether code changed (push) Has been cancelled
End-to-end tests / Build & Package Grafana (push) Has been cancelled
End-to-end tests / Build E2E test runner (push) Has been cancelled
End-to-end tests / push-docker-image (push) Has been cancelled
End-to-end tests / dashboards-suite (old arch) (push) Has been cancelled
End-to-end tests / panels-suite (old arch) (push) Has been cancelled
End-to-end tests / smoke-tests-suite (old arch) (push) Has been cancelled
End-to-end tests / various-suite (old arch) (push) Has been cancelled
End-to-end tests / Verify Storybook (Playwright) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (1/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (2/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (3/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (4/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (5/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (6/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (7/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (8/8) (push) Has been cancelled
End-to-end tests / run-azure-monitor-e2e (push) Has been cancelled
End-to-end tests / All Playwright tests complete (push) Has been cancelled
End-to-end tests / A11y test (push) Has been cancelled
End-to-end tests / Publish metrics (push) Has been cancelled
End-to-end tests / All E2E tests complete (push) Has been cancelled
Frontend tests / Detect whether code changed (push) Has been cancelled
Frontend tests / Unit tests (1 / 16) (push) Has been cancelled
Frontend tests / Unit tests (10 / 16) (push) Has been cancelled
Frontend tests / Unit tests (11 / 16) (push) Has been cancelled
Frontend tests / Unit tests (12 / 16) (push) Has been cancelled
Frontend tests / Unit tests (13 / 16) (push) Has been cancelled
Frontend tests / Unit tests (14 / 16) (push) Has been cancelled
Frontend tests / Unit tests (15 / 16) (push) Has been cancelled
Frontend tests / Unit tests (16 / 16) (push) Has been cancelled
Frontend tests / Unit tests (2 / 16) (push) Has been cancelled
Frontend tests / Unit tests (3 / 16) (push) Has been cancelled
Frontend tests / Unit tests (4 / 16) (push) Has been cancelled
Frontend tests / Unit tests (5 / 16) (push) Has been cancelled
Frontend tests / Unit tests (6 / 16) (push) Has been cancelled
Frontend tests / Unit tests (7 / 16) (push) Has been cancelled
Frontend tests / Unit tests (8 / 16) (push) Has been cancelled
Frontend tests / Unit tests (9 / 16) (push) Has been cancelled
Frontend tests / Decoupled plugin tests (push) Has been cancelled
Frontend tests / Packages unit tests (push) Has been cancelled
Frontend tests / All frontend unit tests complete (push) Has been cancelled
Frontend tests / Devenv frontend-service build (push) Has been cancelled
Integration Tests / Detect whether code changed (push) Has been cancelled
Integration Tests / Sqlite (1/4) (push) Has been cancelled
Integration Tests / Sqlite (2/4) (push) Has been cancelled
Integration Tests / Sqlite (3/4) (push) Has been cancelled
Integration Tests / Sqlite (4/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (1/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (2/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (3/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (4/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (profiled) (push) Has been cancelled
Integration Tests / MySQL (1/16) (push) Has been cancelled
Integration Tests / MySQL (10/16) (push) Has been cancelled
Integration Tests / MySQL (11/16) (push) Has been cancelled
Integration Tests / MySQL (12/16) (push) Has been cancelled
Integration Tests / MySQL (13/16) (push) Has been cancelled
Integration Tests / MySQL (14/16) (push) Has been cancelled
Integration Tests / MySQL (15/16) (push) Has been cancelled
Integration Tests / MySQL (16/16) (push) Has been cancelled
Integration Tests / MySQL (2/16) (push) Has been cancelled
Integration Tests / MySQL (3/16) (push) Has been cancelled
Integration Tests / MySQL (4/16) (push) Has been cancelled
Integration Tests / MySQL (5/16) (push) Has been cancelled
Integration Tests / MySQL (6/16) (push) Has been cancelled
Integration Tests / MySQL (7/16) (push) Has been cancelled
Integration Tests / MySQL (8/16) (push) Has been cancelled
Integration Tests / MySQL (9/16) (push) Has been cancelled
Integration Tests / Postgres (1/16) (push) Has been cancelled
Integration Tests / Postgres (10/16) (push) Has been cancelled
Integration Tests / Postgres (11/16) (push) Has been cancelled
Integration Tests / Postgres (12/16) (push) Has been cancelled
Integration Tests / Postgres (13/16) (push) Has been cancelled
Integration Tests / Postgres (14/16) (push) Has been cancelled
Integration Tests / Postgres (15/16) (push) Has been cancelled
Integration Tests / Postgres (16/16) (push) Has been cancelled
Integration Tests / Postgres (2/16) (push) Has been cancelled
Integration Tests / Postgres (3/16) (push) Has been cancelled
Integration Tests / Postgres (4/16) (push) Has been cancelled
Integration Tests / Postgres (5/16) (push) Has been cancelled
Integration Tests / Postgres (6/16) (push) Has been cancelled
Integration Tests / Postgres (7/16) (push) Has been cancelled
Integration Tests / Postgres (8/16) (push) Has been cancelled
Integration Tests / Postgres (9/16) (push) Has been cancelled
Integration Tests / All backend integration tests complete (push) Has been cancelled
Reject GitHub secrets / reject-gh-secrets (push) Has been cancelled
Build Release Packages / setup (push) Has been cancelled
Build Release Packages / Dispatch grafana-enterprise build (push) Has been cancelled
Build Release Packages / / darwin-amd64 (push) Has been cancelled
Build Release Packages / / darwin-arm64 (push) Has been cancelled
Build Release Packages / / linux-amd64 (push) Has been cancelled
Build Release Packages / / linux-armv6 (push) Has been cancelled
Build Release Packages / / linux-armv7 (push) Has been cancelled
Build Release Packages / / linux-arm64 (push) Has been cancelled
Build Release Packages / / linux-s390x (push) Has been cancelled
Build Release Packages / / windows-amd64 (push) Has been cancelled
Build Release Packages / / windows-arm64 (push) Has been cancelled
Build Release Packages / Upload artifacts (push) Has been cancelled
Build Release Packages / publish-dockerhub (push) Has been cancelled
Build Release Packages / Dispatch publish NPM canaries (push) Has been cancelled
Build Release Packages / notify-pr (push) Has been cancelled
Run dashboard schema v2 e2e / dashboard-schema-v2-e2e (push) Has been cancelled
Shellcheck / Shellcheck scripts (push) Has been cancelled
Run Storybook a11y tests / Detect whether code changed (push) Has been cancelled
Run Storybook a11y tests / Run Storybook a11y tests (light theme) (push) Has been cancelled
Run Storybook a11y tests / Run Storybook a11y tests (dark theme) (push) Has been cancelled
Swagger generated code / Detect whether code changed (push) Has been cancelled
Swagger generated code / Verify committed API specs match (push) Has been cancelled
Dispatch sync to mirror / dispatch-job (push) Has been cancelled
Relyance Compliance Inspection / relyance-compliance-inspector (push) Has been cancelled
Crowdin Download Action / download-sources-from-crowdin (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled
trigger-dashboard-search-e2e / trigger-search-e2e (push) Has been cancelled
Trivy Scan / trivy-scan (push) Has been cancelled
Update `make docs` procedure / main (push) Has been cancelled
* fix: bug preventing users from selecting filter operators
2025-12-04 17:02:54 -06:00
Steve Simpson
4969df8a83 Alerting: Add basic auth options to historian args (#114880) 2025-12-04 22:56:07 +01:00
Steve Simpson
f07cc211bd Alerting: Add command line parsing for historian options (#114865) 2025-12-04 22:07:22 +01:00
alerting-team[bot]
ff33237052 Alerting: Update alerting module to de8c2bbf9eba591078e9d9d7c6cbbe4142ef2d0b (#114877)
[create-pull-request] automated change

Co-authored-by: yuri-tceretian <25988953+yuri-tceretian@users.noreply.github.com>
2025-12-04 20:31:19 +00:00
ismail simsek
0291f6d1e7 Postgresql: Fix variable interpolation logic when the variable has multiple values (#114058)
* fix the variable interpolation

* add jest config to grafana-sql

* fix broken tests

* add variable interpolation tests

* lint

* apply fix only to postresql datasource
2025-12-04 20:58:20 +01:00
beejeebus
26c52796f6 Pass the feature flag instead of false to RegisterAPIService
Doh. The feature flag was not actually being used to enable the new DS
config CRUD APIs. This PR fixes that, hashtag facepalm.
2025-12-04 14:17:45 -05:00
Rafael Bortolon Paulovic
ff97bfc772 fix(unified): key_path column default (#114859)
fix: key_path column default
2025-12-04 12:40:21 -05:00
Andrew Hackmann
665daa5a5d Elasticsearch: Client refactor (#114745)
* split up client.go

* split up search_request.go

* remove double spaces
2025-12-04 11:28:38 -06:00
Costa Alexoglou
42661bed36 feat: add default permissions and DTO support for MT (#114829)
* feat: add default permissions and DTO support for MT

* chore: review comments

* chore: review comments
2025-12-04 18:27:49 +01:00
Collin Fingar
c90677831b Library Panels: Update connection generation for V2 (#114504)
* Library Panels: Update connection generation for V2

* add test

---------

Co-authored-by: Haris Rozajac <haris.rozajac12@gmail.com>
2025-12-04 12:21:27 -05:00
Gabriel MABILLE
59ec85b936 grafana-iam: Fix missing UID (#114856) 2025-12-04 18:00:57 +01:00
Todd Treece
bcaf94f219 Plugins API: Add plugins to RBAC mapper (#114843) 2025-12-04 11:58:49 -05:00
270 changed files with 10655 additions and 4520 deletions

View File

@@ -1,77 +0,0 @@
name: Usability Review Agent
description: Runs AI-powered usability testing using OpenAI Computer Use with Playwright
inputs:
target_url:
description: The URL to test for usability
required: true
openai_api_key:
description: OpenAI API key with Computer Use access
required: true
openai_org:
description: OpenAI organization ID
required: false
grafana_username:
description: Grafana username for authentication
required: false
grafana_password:
description: Grafana password for authentication
required: false
workflow_name:
description: The workflow or feature to test
required: false
default: "the application interface"
prompt_file:
description: Custom prompt file to use (relative to action directory)
required: false
default: "prompt.txt"
output_text_path:
description: Path to save the review output text
required: false
default: "usability-review.txt"
screenshot_path:
description: Path to save the final screenshot
required: false
default: "usability-screenshot.png"
outputs:
review_output:
description: Path to the review output file
value: ${{ inputs.output_text_path }}
screenshot_output:
description: Path to the screenshot file
value: ${{ inputs.screenshot_path }}
runs:
using: "composite"
steps:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
shell: bash
working-directory: ${{ github.action_path }}
run: |
python -m pip install -U pip
pip install -r requirements.txt
python -m playwright install --with-deps chromium
echo "System info:"
free -h || echo "free command not available"
df -h | head -5
- name: Run usability review agent
shell: bash
working-directory: ${{ github.action_path }}
env:
OPENAI_API_KEY: ${{ inputs.openai_api_key }}
OPENAI_ORG: ${{ inputs.openai_org }}
TARGET_URL: ${{ inputs.target_url }}
GRAFANA_USERNAME: ${{ inputs.grafana_username }}
GRAFANA_PASSWORD: ${{ inputs.grafana_password }}
OUTPUT_TEXT_PATH: ${{ github.workspace }}/${{ inputs.output_text_path }}
SCREENSHOT_PATH: ${{ github.workspace }}/${{ inputs.screenshot_path }}
PROMPT_FILE: ${{ github.action_path }}/${{ inputs.prompt_file }}
run: |
python run_agent.py

View File

@@ -1,11 +0,0 @@
from . import default
from . import contrib
from .computer import Computer
from .config import computers_config
__all__ = [
"default",
"contrib",
"Computer",
"computers_config",
]

View File

@@ -1,29 +0,0 @@
from typing import Protocol, List, Literal, Dict
class Computer(Protocol):
"""Defines the 'shape' (methods/properties) our loop expects."""
def get_environment(self) -> Literal["windows", "mac", "linux", "browser"]: ...
def get_dimensions(self) -> tuple[int, int]: ...
def screenshot(self) -> str: ...
def click(self, x: int, y: int, button: str = "left") -> None: ...
def double_click(self, x: int, y: int) -> None: ...
def scroll(self, x: int, y: int, scroll_x: int, scroll_y: int) -> None: ...
def type(self, text: str) -> None: ...
def wait(self, ms: int = 1000) -> None: ...
def move(self, x: int, y: int) -> None: ...
def keypress(self, keys: List[str]) -> None: ...
def drag(self, path: List[Dict[str, int]]) -> None: ...
def get_current_url() -> str: ...

View File

@@ -1,10 +0,0 @@
from .default import *
from .contrib import *
computers_config = {
"local-playwright": LocalPlaywrightBrowser,
"docker": DockerComputer,
"browserbase": BrowserbaseBrowser,
"scrapybara-browser": ScrapybaraBrowser,
"scrapybara-ubuntu": ScrapybaraUbuntu,
}

View File

@@ -1,4 +0,0 @@
from .browserbase import BrowserbaseBrowser
from .local_playwright import LocalPlaywrightBrowser
from .docker import DockerComputer
from .scrapybara import ScrapybaraBrowser, ScrapybaraUbuntu

View File

@@ -1,200 +0,0 @@
import os
from typing import Tuple, Dict, List, Union, Optional
from playwright.sync_api import Browser, Page, BrowserContext, Error as PlaywrightError
from ..shared.base_playwright import BasePlaywrightComputer
from browserbase import Browserbase
from dotenv import load_dotenv
import base64
load_dotenv()
class BrowserbaseBrowser(BasePlaywrightComputer):
"""
Browserbase is a headless browser platform that offers a remote browser API. You can use it to control thousands of browsers from anywhere.
You can find more information about Browserbase at https://www.browserbase.com/computer-use or view our OpenAI CUA Quickstart at https://docs.browserbase.com/integrations/openai-cua/introduction.
IMPORTANT: This Browserbase computer requires the use of the `goto` tool defined in playwright_with_custom_functions.py.
Make sure to include this tool in your configuration when using the Browserbase computer.
"""
def get_dimensions(self):
return self.dimensions
def __init__(
self,
width: int = 1024,
height: int = 768,
region: str = "us-west-2",
proxy: bool = False,
virtual_mouse: bool = True,
ad_blocker: bool = False,
):
"""
Initialize the Browserbase instance. Additional configuration options for features such as persistent cookies, ad blockers, file downloads and more can be found in the Browserbase API documentation: https://docs.browserbase.com/reference/api/create-a-session
Args:
width (int): The width of the browser viewport. Default is 1024.
height (int): The height of the browser viewport. Default is 768.
region (str): The region for the Browserbase session. Default is "us-west-2". Pick a region close to you for better performance. https://docs.browserbase.com/guides/multi-region
proxy (bool): Whether to use a proxy for the session. Default is False. Turn on proxies if you're browsing is frequently interrupted. https://docs.browserbase.com/features/proxies
virtual_mouse (bool): Whether to enable the virtual mouse cursor. Default is True.
ad_blocker (bool): Whether to enable the built-in ad blocker. Default is False.
"""
super().__init__()
self.bb = Browserbase(api_key=os.getenv("BROWSERBASE_API_KEY"))
self.project_id = os.getenv("BROWSERBASE_PROJECT_ID")
self.session = None
self.dimensions = (width, height)
self.region = region
self.proxy = proxy
self.virtual_mouse = virtual_mouse
self.ad_blocker = ad_blocker
def _get_browser_and_page(self) -> Tuple[Browser, Page]:
"""
Create a Browserbase session and connect to it.
Returns:
Tuple[Browser, Page]: A tuple containing the connected browser and page objects.
"""
# Create a session on Browserbase with specified parameters
width, height = self.dimensions
session_params = {
"project_id": self.project_id,
"browser_settings": {
"viewport": {"width": width, "height": height},
"blockAds": self.ad_blocker,
},
"region": self.region,
"proxies": self.proxy,
}
self.session = self.bb.sessions.create(**session_params)
# Print the live session URL
print(
f"Watch and control this browser live at https://www.browserbase.com/sessions/{self.session.id}"
)
# Connect to the remote session
browser = self._playwright.chromium.connect_over_cdp(
self.session.connect_url, timeout=60000
)
context = browser.contexts[0]
# Add event listeners for page creation and closure
context.on("page", self._handle_new_page)
# Only add the init script if virtual_mouse is True
if self.virtual_mouse:
context.add_init_script(
"""
// Only run in the top frame
if (window.self === window.top) {
function initCursor() {
const CURSOR_ID = '__cursor__';
// Check if cursor element already exists
if (document.getElementById(CURSOR_ID)) return;
const cursor = document.createElement('div');
cursor.id = CURSOR_ID;
Object.assign(cursor.style, {
position: 'fixed',
top: '0px',
left: '0px',
width: '20px',
height: '20px',
backgroundImage: 'url("data:image/svg+xml;utf8,<svg xmlns=\\'http://www.w3.org/2000/svg\\' viewBox=\\'0 0 24 24\\' fill=\\'black\\' stroke=\\'white\\' stroke-width=\\'1\\' stroke-linejoin=\\'round\\' stroke-linecap=\\'round\\'><polygon points=\\'2,2 2,22 8,16 14,22 17,19 11,13 20,13\\'/></svg>")',
backgroundSize: 'cover',
pointerEvents: 'none',
zIndex: '99999',
transform: 'translate(-2px, -2px)',
});
document.body.appendChild(cursor);
document.addEventListener("mousemove", (e) => {
cursor.style.top = e.clientY + "px";
cursor.style.left = e.clientX + "px";
});
}
// Use requestAnimationFrame for early execution
requestAnimationFrame(function checkBody() {
if (document.body) {
initCursor();
} else {
requestAnimationFrame(checkBody);
}
});
}
"""
)
page = context.pages[0]
page.on("close", self._handle_page_close)
page.goto("https://bing.com")
return browser, page
def _handle_new_page(self, page: Page):
"""Handle the creation of a new page."""
print("New page created")
self._page = page
page.on("close", self._handle_page_close)
def _handle_page_close(self, page: Page):
"""Handle the closure of a page."""
print("Page closed")
if self._page == page:
if self._browser.contexts[0].pages:
self._page = self._browser.contexts[0].pages[-1]
else:
print("Warning: All pages have been closed.")
self._page = None
def __exit__(self, exc_type, exc_val, exc_tb):
"""
Clean up resources when exiting the context manager.
Args:
exc_type: The type of the exception that caused the context to be exited.
exc_val: The exception instance that caused the context to be exited.
exc_tb: A traceback object encapsulating the call stack at the point where the exception occurred.
"""
if self._page:
self._page.close()
if self._browser:
self._browser.close()
if self._playwright:
self._playwright.stop()
if self.session:
print(
f"Session completed. View replay at https://browserbase.com/sessions/{self.session.id}"
)
def screenshot(self) -> str:
"""
Capture a screenshot of the current viewport using CDP.
Returns:
str: A base64 encoded string of the screenshot.
"""
try:
# Get CDP session from the page
cdp_session = self._page.context.new_cdp_session(self._page)
# Capture screenshot using CDP
result = cdp_session.send(
"Page.captureScreenshot", {"format": "png", "fromSurface": True}
)
return result["data"]
except PlaywrightError as error:
print(
f"CDP screenshot failed, falling back to standard screenshot: {error}"
)
return super().screenshot()

View File

@@ -1,174 +0,0 @@
import subprocess
import time
import shlex
class DockerComputer:
def get_environment(self):
return "linux"
def get_dimensions(self):
return (1280, 720) # Default fallback; will be updated in __enter__.
def __init__(
self,
container_name="cua-sample-app",
image="ghcr.io/openai/openai-cua-sample-app:latest",
display=":99",
port_mapping="5900:5900",
):
self.container_name = container_name
self.image = image
self.display = display
self.port_mapping = port_mapping
def __enter__(self):
# Check if the container is running
result = subprocess.run(
["docker", "ps", "-q", "-f", f"name={self.container_name}"],
capture_output=True,
text=True,
)
if not result.stdout.strip():
raise RuntimeError(
f"Container {self.container_name} is not running. Build and run with:\n"
f"docker build -t {self.container_name} .\n"
f"docker run --rm -it --name {self.container_name} "
f"-p {self.port_mapping} -e DISPLAY={self.display} {self.container_name}"
)
# Fetch display geometry
geometry = self._exec(
f"DISPLAY={self.display} xdotool getdisplaygeometry"
).strip()
if geometry:
w, h = geometry.split()
self.dimensions = (int(w), int(h))
# print("Starting Docker container...")
# # Run the container detached, removing it automatically when it stops
# subprocess.check_call(
# [
# "docker",
# "run",
# "-d",
# "--rm",
# "--name",
# self.container_name,
# "-p",
# self.port_mapping,
# self.image,
# ]
# )
# # Give the container a moment to start
# time.sleep(3)
# print("Entering DockerComputer context")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
# print("Stopping Docker container...")
# subprocess.check_call(["docker", "stop", self.container_name])
# print("Exiting DockerComputer context")
pass
def _exec(self, cmd: str) -> str:
"""
Run 'cmd' in the container.
We wrap cmd in double quotes and escape any double quotes inside it,
so spaces or quotes don't break the shell call.
"""
# Escape any existing double quotes in cmd
safe_cmd = cmd.replace('"', '\\"')
# Then wrap the entire cmd in double quotes for `sh -c`
docker_cmd = f'docker exec {self.container_name} sh -c "{safe_cmd}"'
return subprocess.check_output(docker_cmd, shell=True).decode(
"utf-8", errors="ignore"
)
def screenshot(self) -> str:
"""
Takes a screenshot with ImageMagick (import), returning base64-encoded PNG.
Requires 'import'.
"""
# cmd = (
# f"export DISPLAY={self.display} && "
# "import -window root /tmp/screenshot.png && "
# "base64 /tmp/screenshot.png"
# )
cmd = (
f"export DISPLAY={self.display} && "
"import -window root png:- | base64 -w 0"
)
return self._exec(cmd)
def click(self, x: int, y: int, button: str = "left") -> None:
button_map = {"left": 1, "middle": 2, "right": 3}
b = button_map.get(button, 1)
self._exec(f"DISPLAY={self.display} xdotool mousemove {x} {y} click {b}")
def double_click(self, x: int, y: int) -> None:
self._exec(
f"DISPLAY={self.display} xdotool mousemove {x} {y} click --repeat 2 1"
)
def scroll(self, x: int, y: int, scroll_x: int, scroll_y: int) -> None:
"""
For simple vertical scrolling: xdotool click 4 (scroll up) or 5 (scroll down).
"""
self._exec(f"DISPLAY={self.display} xdotool mousemove {x} {y}")
clicks = abs(scroll_y)
button = 4 if scroll_y < 0 else 5
for _ in range(clicks):
self._exec(f"DISPLAY={self.display} xdotool click {button}")
def type(self, text: str) -> None:
"""
Type the given text via xdotool, preserving spaces and quotes.
"""
# Escape single quotes in the user text: ' -> '\'\''
safe_text = text.replace("'", "'\\''")
# Then wrap everything in single quotes for xdotool
cmd = f"DISPLAY={self.display} xdotool type -- '{safe_text}'"
self._exec(cmd)
def wait(self, ms: int = 1000) -> None:
time.sleep(ms / 1000)
def move(self, x: int, y: int) -> None:
self._exec(f"DISPLAY={self.display} xdotool mousemove {x} {y}")
def keypress(self, keys: list[str]) -> None:
mapping = {
"ENTER": "Return",
"LEFT": "Left",
"RIGHT": "Right",
"UP": "Up",
"DOWN": "Down",
"ESC": "Escape",
"SPACE": "space",
"BACKSPACE": "BackSpace",
"TAB": "Tab",
}
mapped_keys = [mapping.get(key, key) for key in keys]
combo = "+".join(mapped_keys)
self._exec(f"DISPLAY={self.display} xdotool key {combo}")
def drag(self, path: list[dict[str, int]]) -> None:
if not path:
return
start_x = path[0]["x"]
start_y = path[0]["y"]
self._exec(
f"DISPLAY={self.display} xdotool mousemove {start_x} {start_y} mousedown 1"
)
for point in path[1:]:
self._exec(
f"DISPLAY={self.display} xdotool mousemove {point['x']} {point['y']}"
)
self._exec(f"DISPLAY={self.display} xdotool mouseup 1")
def get_current_url(self):
return None

View File

@@ -1,165 +0,0 @@
import os
from playwright.sync_api import Browser, Page
from ..shared.base_playwright import BasePlaywrightComputer
class LocalPlaywrightBrowser(BasePlaywrightComputer):
"""Launches a local Chromium instance using Playwright."""
def __init__(self, headless: bool = False):
super().__init__()
self.headless = headless
def _get_browser_and_page(self) -> tuple[Browser, Page]:
width, height = self.get_dimensions()
launch_args = [
f"--window-size={width},{height}",
"--disable-extensions",
"--disable-file-system",
]
browser = self._playwright.chromium.launch(
chromium_sandbox=False,
headless=self.headless,
args=launch_args,
env={"DISPLAY": ":0"},
)
context = browser.new_context(
user_agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
locale="en-US",
timezone_id="UTC"
)
# Add event listeners for page creation and closure
context.on("page", self._handle_new_page)
page = context.new_page()
page.set_viewport_size({"width": width, "height": height})
page.on("close", self._handle_page_close)
# Add logging for debugging
page.on("console", lambda msg: print(f"Browser console: {msg.text}"))
page.on("pageerror", lambda err: print(f"Page error: {err}"))
target_url = os.environ.get("TARGET_URL", "https://grafana.com/docs/")
grafana_username = os.environ.get("GRAFANA_USERNAME")
grafana_password = os.environ.get("GRAFANA_PASSWORD")
# If credentials provided, log in first
if grafana_username and grafana_password:
from urllib.parse import urlparse, urljoin
base_url = f"{urlparse(target_url).scheme}://{urlparse(target_url).netloc}"
login_url = urljoin(base_url, "/login")
print(f"Logging in to: {login_url}")
page.goto(login_url, timeout=60000)
print(f"Page loaded, current URL: {page.url}")
print(f"Page title: {page.title()}")
try:
# Wait for login form - try multiple selector strategies
print("Waiting for login form to appear...")
# Try to find by placeholder first (more reliable for older versions)
username_field = page.get_by_placeholder("email or username")
password_field = page.get_by_placeholder("password", exact=True)
username_field.wait_for(state="visible", timeout=60000)
print("Login form detected")
# Take screenshot after form is visible
screenshot_path = os.environ.get("GITHUB_WORKSPACE", ".") + "/login_page.png"
page.screenshot(path=screenshot_path)
print(f"Screenshot saved as {screenshot_path}")
# Fill credentials using placeholder selectors
print(f"Filling username (length: {len(grafana_username)})")
username_field.fill(grafana_username)
print(f"Filling password (length: {len(grafana_password)})")
password_field.fill(grafana_password)
print("Credentials filled successfully")
# Click login button by text
print("Clicking login button...")
page.get_by_role("button", name="Log in").click()
print("Login form submitted")
# Wait for login to complete
print("Waiting for post-login navigation...")
# Try to wait for multiple possible indicators of successful login
# The page might redirect to setup guide, dashboard, or other pages
try:
# Wait for either: navigation away from login OR any logged-in UI element
page.locator('body:not(:has-text("Welcome to Grafana Cloud"))').or_(
page.locator('[aria-label="Profile"]')
).or_(
page.locator('a:has-text("Home")')
).first.wait_for(state="attached", timeout=15000)
print(f"Post-login navigation detected, current URL: {page.url}")
# Verify we actually left the login page
if "/login" in page.url:
raise Exception("Still on login page after navigation")
except Exception as wait_err:
print(f"Login completion wait failed: {wait_err}")
if "/login" in page.url:
raise Exception(f"Login failed - still on login page: {page.url}")
else:
print(f"Continuing anyway - URL shows we're logged in: {page.url}")
print(f"Login successful, current URL: {page.url}")
except Exception as e:
print(f"Login failed: {e}")
print(f"Current URL at error: {page.url}")
print(f"Page title at error: {page.title()}")
# Get page content for debugging
try:
body_text = page.locator('body').text_content()
print(f"Page body text (first 500 chars): {body_text[:500] if body_text else 'No body text'}")
except Exception as content_err:
print(f"Could not get page content: {content_err}")
error_screenshot_path = os.environ.get("GITHUB_WORKSPACE", ".") + "/login_error.png"
page.screenshot(path=error_screenshot_path)
print(f"Error screenshot saved as {error_screenshot_path}")
raise
# Set up console and error logging
page.on("console", lambda msg: print(f"Console [{msg.type}]: {msg.text}"))
page.on("pageerror", lambda err: print(f"Page error: {err}"))
print(f"Navigating to: {target_url}")
page.goto(target_url, wait_until="domcontentloaded", timeout=180000)
print(f"Page loaded, URL: {page.url}")
# Wait a bit for Grafana to initialize
print("Waiting for Grafana to initialize...")
page.wait_for_timeout(10000) # Wait 10 seconds for app to settle
print(f"Final URL after waiting: {page.url}")
return browser, page
def _handle_new_page(self, page: Page):
"""Handle the creation of a new page."""
print("New page created")
self._page = page
page.on("close", self._handle_page_close)
def _handle_page_close(self, page: Page):
"""Handle the closure of a page."""
print("Page closed")
if self._page == page:
if self._browser.contexts[0].pages:
self._page = self._browser.contexts[0].pages[-1]
else:
print("Warning: All pages have been closed.")
self._page = None

View File

@@ -1,220 +0,0 @@
import os
import time
from dotenv import load_dotenv
from scrapybara import Scrapybara
from playwright.sync_api import sync_playwright, Browser, Page
from utils import BLOCKED_DOMAINS
load_dotenv()
CUA_KEY_TO_SCRAPYBARA_KEY = {
"/": "slash",
"\\": "backslash",
"arrowdown": "Down",
"arrowleft": "Left",
"arrowright": "Right",
"arrowup": "Up",
"backspace": "BackSpace",
"capslock": "Caps_Lock",
"cmd": "Meta_L",
"delete": "Delete",
"end": "End",
"enter": "Return",
"esc": "Escape",
"home": "Home",
"insert": "Insert",
"option": "Alt_L",
"pagedown": "Page_Down",
"pageup": "Page_Up",
"tab": "Tab",
"win": "Meta_L",
}
class ScrapybaraBrowser:
"""
Scrapybara provides virtual desktops and browsers in the cloud. https://scrapybara.com
You can try OpenAI CUA for free at https://computer.new or read our CUA Quickstart at https://computer.new/cua.
"""
def get_environment(self):
return "browser"
def get_dimensions(self):
return (1024, 768)
def __init__(self):
self.client = Scrapybara(api_key=os.getenv("SCRAPYBARA_API_KEY"))
self._playwright = None
self._browser: Browser | None = None
self._page: Page | None = None
def __enter__(self):
print("Starting scrapybara browser")
blocked_domains = [
domain.replace("https://", "").replace("www.", "")
for domain in BLOCKED_DOMAINS
]
self.instance = self.client.start_browser(blocked_domains=blocked_domains)
print("Scrapybara browser started ₍ᐢ•(ܫ)•ᐢ₎")
print(
f"You can view and interact with the stream at {self.instance.get_stream_url().stream_url}"
)
self._playwright = sync_playwright().start()
self._browser = self._playwright.chromium.connect_over_cdp(
self.instance.get_cdp_url().cdp_url
)
self._page = self._browser.contexts[0].pages[0]
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Stopping scrapybara browser")
self.instance.stop()
print("Scrapybara browser stopped ₍ᐢ-(ェ)-ᐢ₎")
def goto(self, url: str) -> None:
self._page.goto(url)
def get_current_url(self) -> str:
return self.instance.get_current_url().current_url
def screenshot(self) -> str:
return self.instance.screenshot().base_64_image
def click(self, x: int, y: int, button: str = "left") -> None:
button = "middle" if button == "wheel" else button
self.instance.computer(
action="click_mouse",
click_type="click",
button=button,
coordinates=[x, y],
num_clicks=1,
)
def double_click(self, x: int, y: int) -> None:
self.instance.computer(
action="click_mouse",
click_type="click",
button="left",
coordinates=[x, y],
num_clicks=2,
)
def scroll(self, x: int, y: int, scroll_x: int, scroll_y: int) -> None:
self.instance.computer(
action="scroll",
coordinates=[x, y],
delta_x=scroll_x // 20,
delta_y=scroll_y // 20,
)
def type(self, text: str) -> None:
self.instance.computer(action="type_text", text=text)
def wait(self, ms: int = 1000) -> None:
time.sleep(ms / 1000)
# Scrapybara also has `self.instance.computer(action="wait", duration=ms / 1000)`
def move(self, x: int, y: int) -> None:
self.instance.computer(action="move_mouse", coordinates=[x, y])
def keypress(self, keys: list[str]) -> None:
mapped_keys = [
CUA_KEY_TO_SCRAPYBARA_KEY.get(key.lower(), key.lower()) for key in keys
]
self.instance.computer(action="press_key", keys=mapped_keys)
def drag(self, path: list[dict[str, int]]) -> None:
if not path:
return
path = [[point["x"], point["y"]] for point in path]
self.instance.computer(action="drag_mouse", path=path)
class ScrapybaraUbuntu:
"""
Scrapybara provides virtual desktops and browsers in the cloud.
You can try OpenAI CUA for free at https://computer.new or read our CUA Quickstart at https://computer.new/cua.
"""
def get_environment(self):
return "linux"
def get_dimensions(self):
return (1024, 768)
def __init__(self):
self.client = Scrapybara(api_key=os.getenv("SCRAPYBARA_API_KEY"))
def __enter__(self):
print("Starting Scrapybara Ubuntu instance")
blocked_domains = [
domain.replace("https://", "").replace("www.", "")
for domain in BLOCKED_DOMAINS
]
self.instance = self.client.start_ubuntu(blocked_domains=blocked_domains)
print("Scrapybara Ubuntu instance started ₍ᐢ•(ܫ)•ᐢ₎")
print(
f"You can view and interact with the stream at {self.instance.get_stream_url().stream_url}"
)
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Stopping Scrapybara Ubuntu instance")
self.instance.stop()
print("Scrapybara Ubuntu instance stopped ₍ᐢ-(ェ)-ᐢ₎")
def screenshot(self) -> str:
return self.instance.screenshot().base_64_image
def click(self, x: int, y: int, button: str = "left") -> None:
button = "middle" if button == "wheel" else button
self.instance.computer(
action="click_mouse",
click_type="click",
button=button,
coordinates=[x, y],
num_clicks=1,
)
def double_click(self, x: int, y: int) -> None:
self.instance.computer(
action="click_mouse",
click_type="click",
button="left",
coordinates=[x, y],
num_clicks=2,
)
def scroll(self, x: int, y: int, scroll_x: int, scroll_y: int) -> None:
self.instance.computer(
action="scroll",
coordinates=[x, y],
delta_x=scroll_x // 20,
delta_y=scroll_y // 20,
)
def type(self, text: str) -> None:
self.instance.computer(action="type_text", text=text)
def wait(self, ms: int = 1000) -> None:
time.sleep(ms / 1000)
# Scrapybara also has `self.instance.computer(action="wait", duration=ms / 1000)`
def move(self, x: int, y: int) -> None:
self.instance.computer(action="move_mouse", coordinates=[x, y])
def keypress(self, keys: list[str]) -> None:
mapped_keys = [
CUA_KEY_TO_SCRAPYBARA_KEY.get(key.lower(), key.lower()) for key in keys
]
self.instance.computer(action="press_key", keys=mapped_keys)
def drag(self, path: list[dict[str, int]]) -> None:
if not path:
return
path = [[point["x"], point["y"]] for point in path]
self.instance.computer(action="drag_mouse", path=path)
def get_current_url(self):
return None

View File

@@ -1,154 +0,0 @@
import time
import base64
from typing import List, Dict, Literal
from playwright.sync_api import sync_playwright, Browser, Page
from utils import check_blocklisted_url
# Optional: key mapping if your model uses "CUA" style keys
CUA_KEY_TO_PLAYWRIGHT_KEY = {
"/": "Divide",
"\\": "Backslash",
"alt": "Alt",
"arrowdown": "ArrowDown",
"arrowleft": "ArrowLeft",
"arrowright": "ArrowRight",
"arrowup": "ArrowUp",
"backspace": "Backspace",
"capslock": "CapsLock",
"cmd": "Meta",
"ctrl": "Control",
"delete": "Delete",
"end": "End",
"enter": "Enter",
"esc": "Escape",
"home": "Home",
"insert": "Insert",
"option": "Alt",
"pagedown": "PageDown",
"pageup": "PageUp",
"shift": "Shift",
"space": " ",
"super": "Meta",
"tab": "Tab",
"win": "Meta",
}
class BasePlaywrightComputer:
"""
Abstract base for Playwright-based computers:
- Subclasses override `_get_browser_and_page()` to do local or remote connection,
returning (Browser, Page).
- This base class handles context creation (`__enter__`/`__exit__`),
plus standard "Computer" actions like click, scroll, etc.
- We also have extra browser actions: `goto(url)` and `back()`.
"""
def get_environment(self):
return "browser"
def get_dimensions(self):
return (1024, 768)
def __init__(self):
self._playwright = None
self._browser: Browser | None = None
self._page: Page | None = None
def __enter__(self):
# Start Playwright and call the subclass hook for getting browser/page
self._playwright = sync_playwright().start()
self._browser, self._page = self._get_browser_and_page()
# Set up network interception to flag URLs matching domains in BLOCKED_DOMAINS
def handle_route(route, request):
url = request.url
if check_blocklisted_url(url):
print(f"Flagging blocked domain: {url}")
route.abort()
else:
route.continue_()
self._page.route("**/*", handle_route)
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if self._browser:
self._browser.close()
if self._playwright:
self._playwright.stop()
def get_current_url(self) -> str:
return self._page.url
# --- Common "Computer" actions ---
def screenshot(self) -> str:
"""Capture only the viewport (not full_page)."""
png_bytes = self._page.screenshot(full_page=False)
return base64.b64encode(png_bytes).decode("utf-8")
def click(self, x: int, y: int, button: str = "left") -> None:
match button:
case "back":
self.back()
case "forward":
self.forward()
case "wheel":
self._page.mouse.wheel(x, y)
case _:
button_mapping = {"left": "left", "right": "right"}
button_type = button_mapping.get(button, "left")
self._page.mouse.click(x, y, button=button_type)
def double_click(self, x: int, y: int) -> None:
self._page.mouse.dblclick(x, y)
def scroll(self, x: int, y: int, scroll_x: int, scroll_y: int) -> None:
self._page.mouse.move(x, y)
self._page.evaluate(f"window.scrollBy({scroll_x}, {scroll_y})")
def type(self, text: str) -> None:
self._page.keyboard.type(text)
def wait(self, ms: int = 1000) -> None:
time.sleep(ms / 1000)
def move(self, x: int, y: int) -> None:
self._page.mouse.move(x, y)
def keypress(self, keys: List[str]) -> None:
mapped_keys = [CUA_KEY_TO_PLAYWRIGHT_KEY.get(key.lower(), key) for key in keys]
for key in mapped_keys:
self._page.keyboard.down(key)
for key in reversed(mapped_keys):
self._page.keyboard.up(key)
def drag(self, path: List[Dict[str, int]]) -> None:
if not path:
return
self._page.mouse.move(path[0]["x"], path[0]["y"])
self._page.mouse.down()
for point in path[1:]:
self._page.mouse.move(point["x"], point["y"])
self._page.mouse.up()
# --- Extra browser-oriented actions ---
def goto(self, url: str) -> None:
try:
return self._page.goto(url)
except Exception as e:
print(f"Error navigating to {url}: {e}")
def back(self) -> None:
return self._page.go_back()
def forward(self) -> None:
return self._page.go_forward()
# --- Subclass hook ---
def _get_browser_and_page(self) -> tuple[Browser, Page]:
"""Subclasses must implement, returning (Browser, Page)."""
raise NotImplementedError

View File

@@ -1,24 +0,0 @@
openai>=1.56.0
annotated-types==0.7.0
anyio==4.8.0
browserbase==1.2.0
certifi==2025.1.31
charset-normalizer==3.4.1
distro==1.9.0
greenlet==3.1.1
h11==0.14.0
httpcore==1.0.7
httpx==0.28.1
idna==3.10
jiter==0.8.2
pillow==11.1.0
playwright==1.50.0
pydantic==2.10.6
pydantic_core==2.27.2
pyee==12.1.1
python-dotenv==1.0.1
requests==2.32.3
scrapybara>=2.3.6
sniffio==1.3.1
typing_extensions==4.12.2
urllib3==2.3.0

View File

@@ -1,156 +0,0 @@
import os
import base64
from computers import Computer
from computers.default import LocalPlaywrightBrowser
from utils import create_response, check_blocklisted_url
def load_prompt():
"""Load prompt from prompt file (defaults to prompt.txt, can be overridden with PROMPT_FILE env var)."""
prompt_file = os.environ.get("PROMPT_FILE")
if not prompt_file:
prompt_file = os.path.join(os.path.dirname(__file__), "prompt.txt")
if not os.path.exists(prompt_file):
raise FileNotFoundError(f"Prompt file not found: {prompt_file}")
with open(prompt_file, "r", encoding="utf-8") as f:
return f.read().strip()
def acknowledge_safety_check_callback(message: str) -> bool:
# Auto-approve in CI/non-interactive environments
print(f"Safety Check Warning: {message} - Auto-approving in CI mode")
return True
def handle_item(item, computer: Computer):
"""Handle each item; may cause a computer action + screenshot."""
if item["type"] == "message": # print messages
print(item["content"][0]["text"])
if item["type"] == "computer_call": # perform computer actions
action = item["action"]
action_type = action["type"]
action_args = {k: v for k, v in action.items() if k != "type"}
print(f"{action_type}({action_args})")
# give our computer environment action to perform
getattr(computer, action_type)(**action_args)
screenshot_base64 = computer.screenshot()
pending_checks = item.get("pending_safety_checks", [])
for check in pending_checks:
if not acknowledge_safety_check_callback(check["message"]):
raise ValueError(f"Safety check failed: {check['message']}")
# return value informs model of the latest screenshot
call_output = {
"type": "computer_call_output",
"call_id": item["call_id"],
"acknowledged_safety_checks": pending_checks,
"output": {
"type": "input_image",
"image_url": f"data:image/png;base64,{screenshot_base64}",
},
}
# additional URL safety checks for browser environments
if computer.get_environment() == "browser":
current_url = computer.get_current_url()
call_output["output"]["current_url"] = current_url
check_blocklisted_url(current_url)
return [call_output]
return []
def main():
"""Run the CUA (Computer Use Assistant) loop, using Local Playwright."""
output_text_path = os.environ.get("OUTPUT_TEXT_PATH", "output.txt")
screenshot_path = os.environ.get("SCREENSHOT_PATH", "output.png")
all_messages = [] # Collect all model messages
last_screenshot_base64 = None
with LocalPlaywrightBrowser(headless=True) as computer:
dimensions = computer.get_dimensions()
tools = [
{
"type": "computer-preview",
"display_width": dimensions[0],
"display_height": dimensions[1],
"environment": computer.get_environment(),
}
]
items = []
# Load the task prompt from prompt.txt
user_input = load_prompt()
items.append({"role": "user", "content": user_input})
while True: # keep looping until we get a final response
response = create_response(
model="computer-use-preview",
input=items,
tools=tools,
truncation="auto",
)
if "output" not in response:
print(response)
raise ValueError("No output from model")
items += response["output"]
for item in response["output"]:
# Collect all message output from the model
if item.get("type") == "message":
content = item.get("content", [])
for content_item in content:
if isinstance(content_item, dict) and "text" in content_item:
text = content_item["text"]
all_messages.append(text)
result = handle_item(item, computer)
items += result
# Capture last screenshot from computer_call outputs
if result and len(result) > 0:
for output_item in result:
if output_item.get("type") == "computer_call_output":
output = output_item.get("output", {})
if output.get("type") == "input_image":
image_url = output.get("image_url", "")
if image_url.startswith("data:image/png;base64,"):
last_screenshot_base64 = image_url.split(",", 1)[1]
if items[-1].get("role") == "assistant":
break
# Take one final screenshot before closing
if not last_screenshot_base64:
try:
last_screenshot_base64 = computer.screenshot() # Returns base64 string directly
except:
pass
# Save the last screenshot to file
if last_screenshot_base64:
os.makedirs(os.path.dirname(screenshot_path) or ".", exist_ok=True)
with open(screenshot_path, "wb") as f:
f.write(base64.b64decode(last_screenshot_base64))
# Save all model output messages to file
os.makedirs(os.path.dirname(output_text_path) or ".", exist_ok=True)
with open(output_text_path, "w") as f:
if all_messages:
# Join all messages with double newlines for readability
f.write("\n\n".join(all_messages))
else:
# Fallback: save error message if no messages were captured
f.write("No model output messages were captured.")
if __name__ == "__main__":
main()

View File

@@ -1,37 +0,0 @@
import os
import requests
from urllib.parse import urlparse
# Example blocked domains - customize for your use case
BLOCKED_DOMAINS = [
"example-malicious-site.com",
]
def create_response(**kwargs):
url = "https://api.openai.com/v1/responses"
headers = {
"Authorization": f"Bearer {os.getenv('OPENAI_API_KEY')}",
"Content-Type": "application/json"
}
openai_org = os.getenv("OPENAI_ORG")
if openai_org:
headers["Openai-Organization"] = openai_org
response = requests.post(url, headers=headers, json=kwargs)
if response.status_code != 200:
print(f"Error: {response.status_code} {response.text}")
return response.json()
def check_blocklisted_url(url: str) -> None:
"""Raise ValueError if the given URL (including subdomains) is in the blocklist."""
hostname = urlparse(url).hostname or ""
if any(
hostname == blocked or hostname.endswith(f".{blocked}")
for blocked in BLOCKED_DOMAINS
):
raise ValueError(f"Blocked URL: {url}")

View File

@@ -1,189 +0,0 @@
# BabyBot Metrics Export
Export and analyze BabyBot usability review metrics from GitHub.
## Quick Start
```bash
# Export to both CSV and JSON
python .github/scripts/export-babybot-metrics.py
# Export only CSV
python .github/scripts/export-babybot-metrics.py --format csv --output my-metrics
# Export only JSON
python .github/scripts/export-babybot-metrics.py --format json
```
## Output Files
### CSV Format (`babybot-metrics.csv`)
Detailed row-per-comment data, suitable for Excel, Google Sheets, or data analysis tools.
| Column | Description |
|--------|-------------|
| comment_id | GitHub comment ID |
| pr_number | PR number |
| comment_type | `resolvable` or `general` |
| severity | Critical, Major, or Minor |
| confidence | Low, Medium, or High |
| file | File path (for resolvable comments) |
| created_at | Timestamp |
| url | Link to comment |
| total_reactions | Number of reactions (👍, ❤️, 🎉, etc.) |
| has_reply | Boolean - whether comment has replies |
| engagement_score | Calculated engagement score |
### JSON Format (`babybot-metrics.json`)
Aggregated metrics with summaries by PR, severity, and confidence.
```json
{
"total_comments": 42,
"resolvable_comments": 38,
"general_comments": 4,
"by_severity": {
"Critical": 5,
"Major": 20,
"Minor": 17
},
"by_confidence": {
"High": 10,
"Medium": 25,
"Low": 7
},
"engagement": {
"comments_with_reactions": 15,
"comments_with_replies": 8,
"total_reactions": 45,
"avg_reactions_per_comment": 1.07,
"engagement_rate": 35.7
},
"by_pr": {
"114646": {
"count": 3,
"severities": {"Major": 2, "Minor": 1},
"engaged": 2
}
}
}
```
## Dashboard Integration Options
### 1. Google Sheets Dashboard
```bash
# Export CSV and upload to Google Sheets
python .github/scripts/export-babybot-metrics.py --format csv
# Upload babybot-metrics.csv to Google Sheets
# Create pivot tables and charts
```
### 2. Grafana Dashboard
```bash
# Export JSON and serve via HTTP
python .github/scripts/export-babybot-metrics.py --format json
# Use JSON API data source in Grafana
```
### 3. Automated Weekly Reports (GitHub Actions)
See `.github/workflows/babybot-weekly-report.yml` (create this workflow)
### 4. Tableau/Power BI
Import the CSV file directly into your BI tool.
## Metrics Tracked
- **Total comments posted** by BabyBot
- **Resolvable vs general comments** (indicates attachment success rate)
- **Issues by severity** (Critical/Major/Minor breakdown)
- **Issues by confidence** (High/Medium/Low)
- **PRs reviewed** (count and distribution)
- **Comments per PR** (average and trends)
- **Engagement metrics:**
- Comments with reactions (👍, ❤️, 🎉, etc.)
- Comments with replies (developer responses)
- Total reactions count
- Average reactions per comment
- Engagement rate % (how many comments get any response)
## Tracking Comment Engagement (Proxy for "Resolved")
Since GitHub doesn't expose "resolved" status via API, we track **engagement** as a proxy:
### Reactions as Resolution Indicators
Establish a reaction convention with your team:
- ✅ 👍 (`:+1:`) = Acknowledged/Understood
- 🎉 (`:hooray:`) = Fixed/Resolved
- 👀 (`:eyes:`) = Looking into it
- ❤️ (`:heart:`) = Appreciated/Helpful
### Query Engagement
```bash
# Get all BabyBot comments with reactions
gh api repos/grafana/grafana/pulls/comments --paginate \
--jq '.[] | select(.body | contains("BabyBot 🍼")) | {id: .id, reactions: .reactions, pr: .pull_request_url}'
# Count comments with specific reactions (e.g., "resolved" markers)
gh api repos/grafana/grafana/pulls/comments --paginate \
--jq '[.[] | select(.body | contains("BabyBot 🍼")) | .reactions.hooray] | add'
```
### Export shows:
- `total_reactions`: All reactions on the comment
- `has_reply`: Whether developers responded with a comment
- `engagement_score`: Weighted score (reactions + reply bonus)
High engagement score = comment was noticed and actioned! 📊
## Scheduling Automatic Exports
Add to `.github/workflows/babybot-weekly-report.yml`:
```yaml
name: BabyBot Weekly Metrics
on:
schedule:
- cron: '0 9 * * MON' # Every Monday at 9am
workflow_dispatch: # Manual trigger
jobs:
export-metrics:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Export metrics
run: python .github/scripts/export-babybot-metrics.py
- name: Upload to artifact
uses: actions/upload-artifact@v4
with:
name: babybot-metrics-${{ github.run_number }}
path: babybot-metrics.*
- name: Post to Slack
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
run: |
# Parse JSON and send summary to Slack
SUMMARY=$(cat babybot-metrics.json | jq -r '"Total Comments: \(.total_comments), Critical: \(.by_severity.Critical // 0), Major: \(.by_severity.Major // 0)"')
curl -X POST $SLACK_WEBHOOK_URL \
-H 'Content-type: application/json' \
-d "{\"text\": \"📊 Weekly BabyBot Metrics: $SUMMARY\"}"
```
## Example Queries
```bash
# Count by PR
jq '.by_pr | to_entries | map({pr: .key, count: .value.count})' babybot-metrics.json
# Average comments per PR
jq '[.by_pr[].count] | add / length' babybot-metrics.json
# Critical issues percentage
jq '(.by_severity.Critical / .total_comments * 100)' babybot-metrics.json
```

View File

@@ -1,323 +0,0 @@
#!/usr/bin/env python3
"""
Export BabyBot usability review metrics from GitHub
Usage: python export-babybot-metrics.py [--format csv|json] [--output filename]
"""
import subprocess
import json
import csv
import argparse
from datetime import datetime
from collections import defaultdict
def get_prs_with_usability_review_label():
"""Get all PRs with the usability-review label"""
cmd = [
'gh', 'api', 'repos/grafana/grafana/issues',
'--paginate',
'-f', 'state=all',
'-f', 'labels=usability-review',
'--jq', '.[] | .number'
]
result = subprocess.run(cmd, capture_output=True, text=True)
pr_numbers = []
for line in result.stdout.strip().split('\n'):
if line:
try:
pr_numbers.append(line.strip())
except:
continue
return pr_numbers
def get_review_comments(pr_numbers):
"""Get all BabyBot review comments (resolvable ones) from specific PRs"""
comments = []
for pr_number in pr_numbers:
cmd = [
'gh', 'api', f'repos/grafana/grafana/pulls/{pr_number}/comments',
'--jq', '''
.[] |
select(.body | contains("BabyBot 🍼")) |
{
id: .id,
pr_number: (.pull_request_url | split("/") | .[-1]),
file: .path,
line: .line,
created_at: .created_at,
updated_at: .updated_at,
body: .body,
html_url: .html_url,
reactions: .reactions,
in_reply_to_id: .in_reply_to_id
}
'''
]
result = subprocess.run(cmd, capture_output=True, text=True)
for line in result.stdout.strip().split('\n'):
if line:
try:
comments.append(json.loads(line))
except json.JSONDecodeError:
continue
return comments
def get_general_comments(pr_numbers):
"""Get BabyBot general comments (fallback ones) from specific PRs"""
comments = []
for pr_number in pr_numbers:
cmd = [
'gh', 'api', f'repos/grafana/grafana/issues/{pr_number}/comments',
'--jq', '''
.[] |
select(.body | contains("BabyBot 🍼")) |
{
id: .id,
pr_number: (.html_url | split("/") | .[-3]),
created_at: .created_at,
updated_at: .updated_at,
body: .body,
html_url: .html_url,
reactions: .reactions
}
'''
]
result = subprocess.run(cmd, capture_output=True, text=True)
for line in result.stdout.strip().split('\n'):
if line:
try:
comments.append(json.loads(line))
except json.JSONDecodeError:
continue
return comments
def extract_severity(body):
"""Extract severity from comment body"""
if '‼️ Critical' in body:
return 'Critical'
elif '⚠️ Major' in body:
return 'Major'
elif '🟢 Minor' in body:
return 'Minor'
return 'Unknown'
def extract_confidence(body):
"""Extract confidence level from comment body"""
import re
match = re.search(r'\*\*Confidence:\*\*\s*(Low|Medium|High)', body)
return match.group(1) if match else 'Unknown'
def get_replies_to_comment(pr_number, comment_id):
"""Get all replies to a specific comment"""
cmd = [
'gh', 'api', f'repos/grafana/grafana/pulls/{pr_number}/comments',
'--jq', f'.[] | select(.in_reply_to_id == {comment_id})'
]
try:
result = subprocess.run(cmd, capture_output=True, text=True)
replies = []
for line in result.stdout.strip().split('\n'):
if line:
try:
replies.append(json.loads(line))
except json.JSONDecodeError:
continue
return replies
except:
return []
def calculate_engagement_score(comment):
"""Calculate engagement score based on reactions and replies"""
reactions = comment.get('reactions', {})
# Count all reaction types
total_reactions = 0
if isinstance(reactions, dict):
total_reactions = reactions.get('total_count', 0)
# Weight certain reactions more heavily
engagement_reactions = (
reactions.get('+1', 0) + # thumbs up
reactions.get('hooray', 0) + # party
reactions.get('heart', 0) # heart
)
# Check if there are replies
has_reply = comment.get('in_reply_to_id') is not None
# Simple engagement score: reactions + bonus for replies
score = total_reactions + (5 if has_reply else 0)
return {
'total_reactions': total_reactions,
'engagement_reactions': engagement_reactions,
'has_reply': has_reply,
'score': score
}
def aggregate_metrics(review_comments, general_comments):
"""Aggregate metrics by PR and severity"""
metrics = {
'total_comments': len(review_comments) + len(general_comments),
'resolvable_comments': len(review_comments),
'general_comments': len(general_comments),
'by_pr': defaultdict(lambda: {'count': 0, 'severities': defaultdict(int), 'engaged': 0}),
'by_severity': defaultdict(int),
'by_confidence': defaultdict(int),
'engagement': {
'comments_with_reactions': 0,
'comments_with_replies': 0,
'total_reactions': 0,
'avg_reactions_per_comment': 0,
'engagement_rate': 0
},
'export_date': datetime.now().isoformat()
}
all_comments = review_comments + general_comments
total_reactions = 0
comments_with_reactions = 0
comments_with_replies = 0
for comment in all_comments:
pr_num = comment['pr_number']
severity = extract_severity(comment['body'])
confidence = extract_confidence(comment['body'])
# Calculate engagement
engagement = calculate_engagement_score(comment)
metrics['by_pr'][pr_num]['count'] += 1
metrics['by_pr'][pr_num]['severities'][severity] += 1
metrics['by_severity'][severity] += 1
metrics['by_confidence'][confidence] += 1
# Track engagement
if engagement['total_reactions'] > 0:
comments_with_reactions += 1
total_reactions += engagement['total_reactions']
metrics['by_pr'][pr_num]['engaged'] += 1
if engagement['has_reply']:
comments_with_replies += 1
# Calculate engagement metrics
total = len(all_comments)
metrics['engagement']['comments_with_reactions'] = comments_with_reactions
metrics['engagement']['comments_with_replies'] = comments_with_replies
metrics['engagement']['total_reactions'] = total_reactions
metrics['engagement']['avg_reactions_per_comment'] = round(total_reactions / total, 2) if total > 0 else 0
metrics['engagement']['engagement_rate'] = round((comments_with_reactions / total) * 100, 1) if total > 0 else 0
return metrics
def export_to_csv(metrics, review_comments, general_comments, filename):
"""Export detailed metrics to CSV"""
all_comments = review_comments + general_comments
with open(filename, 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=[
'comment_id', 'pr_number', 'comment_type', 'severity',
'confidence', 'file', 'created_at', 'url', 'total_reactions',
'has_reply', 'engagement_score'
])
writer.writeheader()
for comment in all_comments:
engagement = calculate_engagement_score(comment)
writer.writerow({
'comment_id': comment['id'],
'pr_number': comment['pr_number'],
'comment_type': 'resolvable' if 'file' in comment else 'general',
'severity': extract_severity(comment['body']),
'confidence': extract_confidence(comment['body']),
'file': comment.get('file', 'N/A'),
'created_at': comment['created_at'],
'url': comment['html_url'],
'total_reactions': engagement['total_reactions'],
'has_reply': engagement['has_reply'],
'engagement_score': engagement['score']
})
print(f"✅ Exported detailed metrics to {filename}")
def export_to_json(metrics, filename):
"""Export aggregated metrics to JSON"""
with open(filename, 'w') as f:
json.dump(metrics, f, indent=2)
print(f"✅ Exported aggregated metrics to {filename}")
def print_summary(metrics):
"""Print summary to console"""
print("\n📊 BabyBot Usability Review Metrics")
print("=" * 50)
print(f"Total Comments: {metrics['total_comments']}")
print(f" - Resolvable (on files): {metrics['resolvable_comments']}")
print(f" - General: {metrics['general_comments']}")
print(f"\nBy Severity:")
for severity, count in metrics['by_severity'].items():
print(f" - {severity}: {count}")
print(f"\nBy Confidence:")
for confidence, count in metrics['by_confidence'].items():
print(f" - {confidence}: {count}")
print(f"\nEngagement:")
eng = metrics['engagement']
print(f" - Comments with reactions: {eng['comments_with_reactions']}")
print(f" - Comments with replies: {eng['comments_with_replies']}")
print(f" - Total reactions: {eng['total_reactions']}")
print(f" - Avg reactions per comment: {eng['avg_reactions_per_comment']}")
print(f" - Engagement rate: {eng['engagement_rate']}%")
print(f"\nPRs Reviewed: {len(metrics['by_pr'])}")
print("=" * 50)
def main():
parser = argparse.ArgumentParser(description='Export BabyBot metrics')
parser.add_argument('--format', choices=['csv', 'json', 'both'], default='both',
help='Export format (default: both)')
parser.add_argument('--output', default='babybot-metrics',
help='Output filename (without extension)')
args = parser.parse_args()
print("🔍 Fetching PRs with 'usability-review' label...")
pr_numbers = get_prs_with_usability_review_label()
print(f"Found {len(pr_numbers)} PRs with usability-review label")
if not pr_numbers:
print("No PRs found with usability-review label. Exiting.")
return
print("\n🔍 Fetching BabyBot comments from those PRs...")
review_comments = get_review_comments(pr_numbers)
general_comments = get_general_comments(pr_numbers)
print(f"Found {len(review_comments)} review comments and {len(general_comments)} general comments")
print("\n📈 Aggregating metrics...")
metrics = aggregate_metrics(review_comments, general_comments)
print_summary(metrics)
if args.format in ['csv', 'both']:
export_to_csv(metrics, review_comments, general_comments, f"{args.output}.csv")
if args.format in ['json', 'both']:
export_to_json(metrics, f"{args.output}.json")
print("\n✨ Done!")
if __name__ == '__main__':
main()

View File

@@ -1,11 +1,11 @@
name: Add comment about adding a What's new note
name: Add comment about adding a What's new note for either what's new or breaking changes
on:
pull_request:
types: [labeled]
jobs:
add-comment:
if: ${{ ! github.event.pull_request.head.repo.fork && contains(github.event.pull_request.labels.*.name, 'add to what''s new') }}
if: ${{ ! github.event.pull_request.head.repo.fork && (contains(github.event.pull_request.labels.*.name, 'add to what''s new') || contains(github.event.pull_request.labels.*.name, 'breaking change') || contains(github.event.pull_request.labels.*.name, 'levitate breaking change')) }}
runs-on: ubuntu-latest
permissions:
pull-requests: write
@@ -13,4 +13,4 @@ jobs:
- uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 # v2.9.4
with:
message: |
Since you've added the `Add to what's new` label, consider drafting a [What's new note](https://admin.grafana.com/content-admin/#/collections/whats-new/new) for this feature.
Since you've added the `What's New` or a breaking change label, consider drafting a [What's new note](https://admin.grafana.com/content-admin/#/collections/whats-new/new) for this feature.

View File

@@ -1,127 +0,0 @@
name: BabyBot Weekly Metrics Report
on:
schedule:
- cron: '0 9 * * MON' # Every Monday at 9am UTC
workflow_dispatch: # Allow manual trigger
permissions:
contents: read
id-token: write
jobs:
export-metrics:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Export BabyBot metrics
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python .github/scripts/export-babybot-metrics.py --format both --output babybot-metrics-$(date +%Y-%m-%d)
- name: Upload metrics artifacts
uses: actions/upload-artifact@v4
with:
name: babybot-metrics-${{ github.run_number }}
path: |
babybot-metrics-*.csv
babybot-metrics-*.json
retention-days: 90
- name: Generate summary
id: summary
run: |
METRICS_FILE=$(ls babybot-metrics-*.json | head -1)
TOTAL=$(jq -r '.total_comments' $METRICS_FILE)
RESOLVABLE=$(jq -r '.resolvable_comments' $METRICS_FILE)
CRITICAL=$(jq -r '.by_severity.Critical // 0' $METRICS_FILE)
MAJOR=$(jq -r '.by_severity.Major // 0' $METRICS_FILE)
MINOR=$(jq -r '.by_severity.Minor // 0' $METRICS_FILE)
PRS=$(jq -r '.by_pr | length' $METRICS_FILE)
echo "total=$TOTAL" >> $GITHUB_OUTPUT
echo "resolvable=$RESOLVABLE" >> $GITHUB_OUTPUT
echo "critical=$CRITICAL" >> $GITHUB_OUTPUT
echo "major=$MAJOR" >> $GITHUB_OUTPUT
echo "minor=$MINOR" >> $GITHUB_OUTPUT
echo "prs=$PRS" >> $GITHUB_OUTPUT
- name: Post summary to Slack
if: env.SLACK_WEBHOOK_URL != ''
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
TOTAL: ${{ steps.summary.outputs.total }}
RESOLVABLE: ${{ steps.summary.outputs.resolvable }}
CRITICAL: ${{ steps.summary.outputs.critical }}
MAJOR: ${{ steps.summary.outputs.major }}
MINOR: ${{ steps.summary.outputs.minor }}
PRS: ${{ steps.summary.outputs.prs }}
run: |
curl -X POST $SLACK_WEBHOOK_URL \
-H 'Content-type: application/json' \
-d "{
\"channel\": \"#hackathon15-agentic-usability-review\",
\"username\": \"BabyBot Metrics\",
\"icon_emoji\": \":bar_chart:\",
\"blocks\": [
{
\"type\": \"header\",
\"text\": {
\"type\": \"plain_text\",
\"text\": \"📊 BabyBot Weekly Metrics Report\"
}
},
{
\"type\": \"section\",
\"text\": {
\"type\": \"mrkdwn\",
\"text\": \"*Total Comments:* $TOTAL\\n*Resolvable:* $RESOLVABLE\\n*PRs Reviewed:* $PRS\"
}
},
{
\"type\": \"section\",
\"text\": {
\"type\": \"mrkdwn\",
\"text\": \"*By Severity*\\n• ‼️ Critical: $CRITICAL\\n• ⚠️ Major: $MAJOR\\n• 🟢 Minor: $MINOR\"
}
},
{
\"type\": \"actions\",
\"elements\": [
{
\"type\": \"button\",
\"text\": {
\"type\": \"plain_text\",
\"text\": \"Download Full Report\"
},
\"url\": \"https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\"
}
]
}
]
}"
- name: Create summary comment (optional - for visibility)
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "## 📊 BabyBot Metrics Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Total Comments:** ${{ steps.summary.outputs.total }}" >> $GITHUB_STEP_SUMMARY
echo "**Resolvable Comments:** ${{ steps.summary.outputs.resolvable }}" >> $GITHUB_STEP_SUMMARY
echo "**PRs Reviewed:** ${{ steps.summary.outputs.prs }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### By Severity" >> $GITHUB_STEP_SUMMARY
echo "- ‼️ Critical: ${{ steps.summary.outputs.critical }}" >> $GITHUB_STEP_SUMMARY
echo "- ⚠️ Major: ${{ steps.summary.outputs.major }}" >> $GITHUB_STEP_SUMMARY
echo "- 🟢 Minor: ${{ steps.summary.outputs.minor }}" >> $GITHUB_STEP_SUMMARY

View File

@@ -1,613 +0,0 @@
name: Usability Review Agent
on:
issue_comment:
types: [created]
pull_request:
types: [labeled]
permissions:
contents: read
pull-requests: write
issues: write
id-token: write
env:
OUTPUT_TEXT_PATH: usability-review.txt
SCREENSHOT_PATH: usability-screenshot.png
jobs:
usability-review:
# Run when either: (1) someone comments '/test-me-baby-one-more-time' on a PR, or (2) 'usability-review' label is added
if: ${{ (github.event.issue.pull_request && startsWith(github.event.comment.body, '/test-me-baby-one-more-time')) || github.event.label.name == 'usability-review' }}
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: React to comment
if: github.event_name == 'issue_comment'
uses: actions/github-script@v7
with:
script: |
github.rest.reactions.createForIssueComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: context.payload.comment.id,
content: 'rocket'
});
- name: Post acknowledgment
if: github.event_name == 'issue_comment'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.issue.number }}
run: |
gh pr comment $PR_NUMBER --body "🤖 Starting usability review... This may take a few minutes."
- name: Set PR number
id: pr-number
run: |
if [ "${{ github.event_name }}" = "issue_comment" ]; then
echo "number=${{ github.event.issue.number }}" >> $GITHUB_OUTPUT
else
echo "number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
fi
- name: Extract target URL from ephemeral instance comment
id: extract-url
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ steps.pr-number.outputs.number }}
run: |
# Extract ephemeral instance URL from PR comments
# Looks for the most recent comment containing: https://ephemeral{alphanumeric}.grafana-dev.net
#
# TODO: Future improvement - auto-trigger deployment if no URL found:
# 1. Comment /deploy-to-hg on the PR
# 2. Wait ~20 minutes for build to complete
# 3. Retry extracting URL
# 4. Continue with usability review
# Get all PR comments, newest first
COMMENTS=$(gh pr view $PR_NUMBER --json comments --jq '.comments | reverse | .[].body')
# Find the most recent comment with ephemeral instance URL (alphanumeric subdomain)
TARGET_URL=$(echo "$COMMENTS" | grep -oE 'https://ephemeral[a-zA-Z0-9]+\.grafana-dev\.net' | head -1)
if [ -z "$TARGET_URL" ]; then
echo "::error::No ephemeral instance URL found in PR comments"
echo "::notice::Please deploy an ephemeral instance first by commenting /deploy-to-hg"
exit 1
fi
echo "Found target URL: $TARGET_URL"
echo "TARGET_URL=$TARGET_URL" >> $GITHUB_ENV
- name: "Get vault secrets (dev)"
id: vault-secrets-dev
uses: grafana/shared-workflows/actions/get-vault-secrets@get-vault-secrets/v1.3.0
with:
vault_instance: "dev"
repo_secrets: |
GCOM_HOST=usability-review-agent:GCOM_HOST
GCOM_TOKEN=usability-review-agent:GCOM_TOKEN
OPENAI_API_KEY=usability-review-agent:OPENAI_API_KEY
GRAFANA_USERNAME=usability-review-agent:GRAFANA_USERNAME
GRAFANA_PASSWORD=usability-review-agent:GRAFANA_PASSWORD
SLACK_WEBHOOK_URL=usability-review-agent:SLACK_WEBHOOK_URL
- name: "Get vault secrets (ops) - GitHub App credentials"
id: vault-secrets-ops
uses: grafana/shared-workflows/actions/get-vault-secrets@main
with:
repo_secrets: |
APP_ID=ephemeral-instances-bot:app-id
APP_PEM=ephemeral-instances-bot:app-private-key
- name: "Generate GitHub App token for private repo access"
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
with:
app_id: ${{ env.APP_ID }}
private_key: ${{ env.APP_PEM }}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install OpenAI package
run: |
python -m pip install -U pip
pip install openai
- name: Get PR details
id: pr-details
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ steps.pr-number.outputs.number }}
run: |
# Get PR title, body, and changed files
PR_DATA=$(gh pr view $PR_NUMBER --json title,body,files)
PR_TITLE=$(echo "$PR_DATA" | jq -r '.title')
PR_BODY=$(echo "$PR_DATA" | jq -r '.body // ""')
# Get list of changed files
CHANGED_FILES=$(echo "$PR_DATA" | jq -r '.files[].path' | head -20)
# Save to files for next step
echo "$PR_TITLE" > pr_title.txt
echo "$PR_BODY" > pr_body.txt
echo "$CHANGED_FILES" > changed_files.txt
echo "PR Title: $PR_TITLE"
echo "Changed files count: $(echo "$CHANGED_FILES" | wc -l)"
- name: Generate PR summary
id: pr-summary
env:
OPENAI_API_KEY: ${{ env.OPENAI_API_KEY }}
run: |
python - <<'PY'
import os
from openai import OpenAI
client = OpenAI()
# Read PR details
with open("pr_title.txt", "r") as f:
pr_title = f.read().strip()
with open("pr_body.txt", "r") as f:
pr_body = f.read().strip()
with open("changed_files.txt", "r") as f:
changed_files = f.read().strip()
# Generate summary of what the PR does
system = "You are a technical analyst summarizing pull request changes."
user = f"""Analyze this PR and provide a 2-3 sentence summary of what feature/change is being implemented:
PR Title: {pr_title}
PR Description: {pr_body if pr_body else "(No description provided)"}
Changed Files:
{changed_files}
Focus on what the user-facing impact is and what functionality is being added or modified."""
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system},
{"role": "user", "content": user},
],
)
pr_summary = resp.choices[0].message.content.strip()
with open("pr_summary.txt", "w") as f:
f.write(pr_summary)
print(f"PR Summary: {pr_summary}")
PY
- name: Fetch prompt from external repo
env:
GH_TOKEN: ${{ steps.generate_token.outputs.token }}
run: |
# Fetch prompt from private repo using GitHub API
gh api \
-H "Accept: application/vnd.github.raw" \
/repos/grafana/usability-review-agent-github-action/contents/prompts/single/reviewer.md \
> base_prompt.txt
echo "Fetched prompt from external repo"
echo "Prompt size: $(wc -c < base_prompt.txt) bytes"
echo "First 100 chars: $(head -c 100 base_prompt.txt)"
- name: Build dynamic prompt
id: build-prompt
run: |
# Read the PR summary
PR_SUMMARY=$(cat pr_summary.txt)
# Read base prompt template from external repo
BASE_PROMPT=$(cat base_prompt.txt)
# Build dynamic prompt with PR context
cat > dynamic_prompt.txt <<EOF
## Context
You are reviewing a pull request that makes the following changes:
$PR_SUMMARY
Your task is to test the workflow and provide usability feedback.
## Instructions
$BASE_PROMPT
EOF
# Copy to action directory so it can be used
cp dynamic_prompt.txt .github/actions/usability-review-agent/dynamic_prompt.txt
echo "Dynamic prompt created"
- name: Extract instance slug from URL
run: |
INSTANCE_SLUG=$(echo "${{ env.TARGET_URL }}" | sed -E 's|https?://([^.]+)\..*|\1|')
echo "Instance slug: $INSTANCE_SLUG"
echo "INSTANCE_SLUG=$INSTANCE_SLUG" >> $GITHUB_ENV
- name: Enable basic auth on instance
env:
GCOM_HOST: ${{ env.GCOM_HOST }}
GCOM_TOKEN: ${{ env.GCOM_TOKEN }}
INSTANCE_SLUG: ${{ env.INSTANCE_SLUG }}
run: |
# Check current config
CURRENT_CONFIG=$(curl -s "${GCOM_HOST}/api/instances/${INSTANCE_SLUG}/config" \
-H "Authorization: Bearer ${GCOM_TOKEN}")
DISABLE_LOGIN_FORM=$(echo "$CURRENT_CONFIG" | jq -r '.auth.disable_login_form // true')
echo "Current disable_login_form: $DISABLE_LOGIN_FORM"
if [ "$DISABLE_LOGIN_FORM" != "false" ]; then
echo "Enabling basic auth..."
curl -X POST "${GCOM_HOST}/api/instances/${INSTANCE_SLUG}/config" \
-H "Authorization: Bearer ${GCOM_TOKEN}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d 'config[auth][disable_login_form]=false'
echo "Waiting for pod restart..."
sleep 300
# Verify instance is ready
for i in {1..10}; do
if curl -sf https://${INSTANCE_SLUG}.grafana-dev.net/api/health; then
echo "Instance ready!"
break
fi
echo "Attempt $i failed, waiting..."
sleep 10
done
else
echo "Basic auth already enabled, skipping..."
fi
- name: Create test user for playwright
# Using system realm token with stack-users:write scope
env:
GCOM_HOST: ${{ env.GCOM_HOST }}
GCOM_TOKEN: ${{ env.GCOM_TOKEN }}
INSTANCE_SLUG: ${{ env.INSTANCE_SLUG }}
GRAFANA_USERNAME: ${{ env.GRAFANA_USERNAME }}
GRAFANA_PASSWORD: ${{ env.GRAFANA_PASSWORD }}
run: |
pip install requests
python3 <<'PYTHON'
import os, requests, json
gcom_host = os.environ['GCOM_HOST']
gcom_token = os.environ['GCOM_TOKEN']
instance = os.environ['INSTANCE_SLUG']
username = os.environ['GRAFANA_USERNAME']
password = os.environ['GRAFANA_PASSWORD']
# Create user via GCOM API (proxies to instance /api/admin/users)
resp = requests.post(
f"{gcom_host}/api/instances/{instance}/api/admin/users",
headers={"Authorization": f"Bearer {gcom_token}"},
json={"name": "Usability Review Agent", "login": username, "password": password}
)
if resp.status_code == 412:
print(f"Test user already exists (412), skipping creation")
elif resp.status_code >= 400:
print(f"Error creating user: {resp.status_code} {resp.text}")
resp.raise_for_status()
else:
user_id = resp.json()['id']
print(f"Created new test user (id: {user_id})")
# Make user admin via GCOM API (proxies to instance)
perm_resp = requests.put(
f"{gcom_host}/api/instances/{instance}/api/admin/users/{user_id}/permissions",
headers={"Authorization": f"Bearer {gcom_token}"},
json={"isGrafanaAdmin": True}
)
if perm_resp.status_code >= 400:
print(f"Warning: Failed to set admin permissions: {perm_resp.status_code}")
else:
print(f"Set admin permissions for test user")
print(f"Test user setup complete")
PYTHON
- name: Run usability review agent
uses: ./.github/actions/usability-review-agent
with:
target_url: ${{ env.TARGET_URL }}
openai_api_key: ${{ env.OPENAI_API_KEY }}
grafana_username: ${{ env.GRAFANA_USERNAME }}
grafana_password: ${{ env.GRAFANA_PASSWORD }}
workflow_name: "the application interface"
prompt_file: "dynamic_prompt.txt"
output_text_path: ${{ env.OUTPUT_TEXT_PATH }}
screenshot_path: ${{ env.SCREENSHOT_PATH }}
- name: Upload review artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: usability-review-results
path: |
${{ env.OUTPUT_TEXT_PATH }}
${{ env.SCREENSHOT_PATH }}
login_page.png
login_error.png
if-no-files-found: warn
retention-days: 7
- name: Post review results to PR
if: always()
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ steps.pr-number.outputs.number }}
RUN_ID: ${{ github.run_id }}
run: |
COMMENT_FILE=$(mktemp)
echo "## 🔍 Usability Review Results" > "$COMMENT_FILE"
echo "" >> "$COMMENT_FILE"
echo "**Target URL:** ${{ env.TARGET_URL }}" >> "$COMMENT_FILE"
echo "" >> "$COMMENT_FILE"
echo "---" >> "$COMMENT_FILE"
echo "" >> "$COMMENT_FILE"
if [ -s ${{ env.OUTPUT_TEXT_PATH }} ]; then
cat ${{ env.OUTPUT_TEXT_PATH }} >> "$COMMENT_FILE"
else
echo "⚠️ No review output was generated." >> "$COMMENT_FILE"
fi
echo "" >> "$COMMENT_FILE"
echo "---" >> "$COMMENT_FILE"
echo "" >> "$COMMENT_FILE"
echo "📸 [View screenshot and full artifacts](https://github.com/${{ github.repository }}/actions/runs/$RUN_ID)" >> "$COMMENT_FILE"
gh pr comment $PR_NUMBER --body-file "$COMMENT_FILE"
rm "$COMMENT_FILE"
- name: Post individual suggestions as separate comments
if: always()
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ steps.pr-number.outputs.number }}
OUTPUT_TEXT_PATH: ${{ env.OUTPUT_TEXT_PATH }}
run: |
python3 <<'PYTHON'
import os
import subprocess
import re
import json
# Read the AI output
output_path = os.environ['OUTPUT_TEXT_PATH']
if not os.path.exists(output_path) or os.path.getsize(output_path) == 0:
print("No output file found, skipping individual comments")
exit(0)
with open(output_path, 'r') as f:
content = f.read()
# Extract table rows (skip header and separator)
# New format: | Issue | Severity | Impact | Confidence | Suggestion |
table_pattern = r'\|([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|'
matches = re.findall(table_pattern, content)
if len(matches) < 3:
print(f"Not enough table rows found ({len(matches)}), skipping individual comments")
exit(0)
# Skip first 2 matches (header + separator)
issue_rows = matches[2:] # Get all issues after header
pr_number = os.environ['PR_NUMBER']
# Get changed files in the PR to attach comments to
pr_files_result = subprocess.run(
['gh', 'pr', 'view', pr_number, '--json', 'files'],
capture_output=True,
text=True,
check=True
)
pr_data = json.loads(pr_files_result.stdout)
changed_files = [f['path'] for f in pr_data.get('files', [])]
# Prefer frontend files for UI issues
frontend_files = [f for f in changed_files if any(ext in f for ext in ['.tsx', '.ts', '.jsx', '.js', '.vue', '.css', '.scss'])]
target_files = frontend_files if frontend_files else changed_files
if not target_files:
print("No changed files found, posting as general comments instead")
target_files = [None] * len(issue_rows)
for idx, (issue, severity, impact, confidence, suggestion) in enumerate(issue_rows):
# Clean up whitespace
issue = issue.strip()
severity = severity.strip()
impact = impact.strip()
confidence = confidence.strip()
suggestion = suggestion.strip()
# Extract issue title from markdown (bold text before <br />)
issue_title_match = re.search(r'\*\*(.+?)\*\*', issue)
issue_title = issue_title_match.group(1) if issue_title_match else issue
# Create individual comment
comment = f"""### {severity} {issue_title}
**Confidence:** {confidence}
**Impact:** {impact}
**Suggestion:** {suggestion}
---
_Posted by BabyBot 🍼 - Usability Review Agent_"""
# Try to post as review comment (resolvable) on a changed file
target_file = target_files[idx % len(target_files)] if target_files[0] is not None else None
if target_file:
# Post as review comment on the file (resolvable!)
try:
# Create a review comment on line 1 of the file
subprocess.run(
['gh', 'pr', 'review', pr_number, '--comment', '--body', comment, '--file', target_file, '--line', '1'],
check=True,
capture_output=True
)
print(f"Posted resolvable comment for: {issue_title} (on {target_file})")
except subprocess.CalledProcessError as e:
# Fallback to general comment if review comment fails
print(f"Failed to post review comment, falling back to general comment: {e}")
subprocess.run(
['gh', 'pr', 'comment', pr_number, '--body', comment],
check=True
)
print(f"Posted general comment for: {issue_title}")
else:
# Post as general comment
subprocess.run(
['gh', 'pr', 'comment', pr_number, '--body', comment],
check=True
)
print(f"Posted general comment for: {issue_title}")
PYTHON
- name: Send Slack notification on success
if: always()
env:
SLACK_WEBHOOK_URL: ${{ env.SLACK_WEBHOOK_URL }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ steps.pr-number.outputs.number }}
OUTPUT_TEXT_PATH: ${{ env.OUTPUT_TEXT_PATH }}
run: |
# Check if Slack webhook is configured
if [ -z "$SLACK_WEBHOOK_URL" ]; then
echo "Slack webhook not configured, skipping notification"
exit 0
fi
# Check if review was successful
if [ ! -s ${{ env.OUTPUT_TEXT_PATH }} ]; then
echo "No review output found, skipping success notification"
exit 0
fi
# Fetch PR details and export for Python
PR_DATA=$(gh pr view $PR_NUMBER --json title,url,author)
export PR_TITLE=$(echo "$PR_DATA" | jq -r '.title')
export PR_URL=$(echo "$PR_DATA" | jq -r '.url')
export PR_AUTHOR=$(echo "$PR_DATA" | jq -r '.author.login')
python3 <<'PYTHON'
import os
import json
import subprocess
import re
# Read the AI output to extract issues
with open(os.environ['OUTPUT_TEXT_PATH'], 'r') as f:
content = f.read()
# Extract table rows for issues
# New format: | Issue | Severity | Impact | Confidence | Suggestion |
table_pattern = r'\|([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|'
matches = re.findall(table_pattern, content)
# Build issues text
issues_text = ""
if len(matches) >= 3:
issue_rows = matches[2:] # Skip header rows
for issue, severity, impact, confidence, suggestion in issue_rows:
issue = issue.strip()
severity = severity.strip()
suggestion = suggestion.strip()
# Extract issue title from markdown
issue_title_match = re.search(r'\*\*(.+?)\*\*', issue)
issue_title = issue_title_match.group(1) if issue_title_match else issue
issues_text += f"• *{severity}* {issue_title}\n → {suggestion}\n"
else:
issues_text = "No specific issues found"
pr_number = os.environ['PR_NUMBER']
pr_title = os.environ['PR_TITLE']
pr_url = os.environ['PR_URL']
pr_author = os.environ['PR_AUTHOR']
# Build Slack message
slack_payload = {
"channel": "#hackathon15-agentic-usability-review",
"username": "Usability Review Agent",
"icon_emoji": ":mag:",
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": f"✅ Usability Review Complete: PR #{pr_number}",
"emoji": True
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": f"*<{pr_url}|{pr_title}>*\nby @{pr_author}"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": f"*Issues & Suggestions*\n{issues_text}"
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "View Full Review",
"emoji": True
},
"url": pr_url
}
]
}
]
}
# Send to Slack
webhook_url = os.environ['SLACK_WEBHOOK_URL']
subprocess.run(
['curl', '-X', 'POST', '-H', 'Content-type: application/json',
'--data', json.dumps(slack_payload), webhook_url],
check=True
)
print("Slack notification sent successfully")
PYTHON

View File

@@ -8,7 +8,7 @@ require (
github.com/google/go-github/v70 v70.0.0
github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4
github.com/grafana/grafana v0.0.0-00010101000000-000000000000
github.com/grafana/grafana-app-sdk v0.48.4
github.com/grafana/grafana-app-sdk v0.48.5
github.com/grafana/grafana-app-sdk/logging v0.48.3
github.com/grafana/grafana-plugin-sdk-go v0.284.0
github.com/grafana/grafana/pkg/apimachinery v0.0.0

View File

@@ -618,8 +618,8 @@ github.com/grafana/dataplane/sdata v0.0.9 h1:AGL1LZnCUG4MnQtnWpBPbQ8ZpptaZs14w6k
github.com/grafana/dataplane/sdata v0.0.9/go.mod h1:Jvs5ddpGmn6vcxT7tCTWAZ1mgi4sbcdFt9utQx5uMAU=
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 h1:jSojuc7njleS3UOz223WDlXOinmuLAIPI0z2vtq8EgI=
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4/go.mod h1:VahT+GtfQIM+o8ht2StR6J9g+Ef+C2Vokh5uuSmOD/4=
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
github.com/grafana/grafana-aws-sdk v1.3.0 h1:/bfJzP93rCel1GbWoRSq0oUo424MZXt8jAp2BK9w8tM=

View File

@@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/alerting/alertenrichment
go 1.25.5
require (
github.com/grafana/grafana-app-sdk v0.48.4
github.com/grafana/grafana-app-sdk v0.48.5
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250901080157-a0280d701b28
k8s.io/apimachinery v0.34.2
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912

View File

@@ -23,8 +23,8 @@ github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7O
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250901080157-a0280d701b28 h1:PgMfX4OPENz/iXmtDDIW9+poZY4UD0hhmXm7flVclDo=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250901080157-a0280d701b28/go.mod h1:av5N0Naq+8VV9MLF7zAkihy/mVq5UbS2EvRSJukDHlY=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=

View File

@@ -6,7 +6,7 @@ require (
github.com/go-kit/log v0.2.1
github.com/grafana/alerting v0.0.0-20251204145817-de8c2bbf9eba
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4
github.com/grafana/grafana-app-sdk v0.48.4
github.com/grafana/grafana-app-sdk v0.48.5
github.com/grafana/grafana-app-sdk/logging v0.48.3
github.com/prometheus/client_golang v1.23.2
github.com/spf13/pflag v1.0.10

View File

@@ -216,14 +216,14 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/grafana/alerting v0.0.0-20251204145817-de8c2bbf9eba h1:psKWNETD5nGxmFAlqnWsXoRyUwSa2GHNEMSEDKGKfQ4=
github.com/grafana/alerting v0.0.0-20251204145817-de8c2bbf9eba/go.mod h1:l7v67cgP7x72ajB9UPZlumdrHqNztpKoqQ52cU8T3LU=
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 h1:jSojuc7njleS3UOz223WDlXOinmuLAIPI0z2vtq8EgI=
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4/go.mod h1:VahT+GtfQIM+o8ht2StR6J9g+Ef+C2Vokh5uuSmOD/4=
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
github.com/grafana/loki/pkg/push v0.0.0-20250823105456-332df2b20000 h1:/5LKSYgLmAhwA4m6iGUD4w1YkydEWWjazn9qxCFT8W0=

View File

@@ -1,6 +1,7 @@
package config
import (
"net/http"
"net/url"
"time"
@@ -15,9 +16,14 @@ const (
lokiDefaultMaxQuerySize = 65536 // 64kb
)
type LokiConfig struct {
lokiclient.LokiConfig
Transport http.RoundTripper
}
type NotificationConfig struct {
Enabled bool
Loki lokiclient.LokiConfig
Loki LokiConfig
}
type RuntimeConfig struct {
@@ -27,7 +33,7 @@ type RuntimeConfig struct {
func (n *NotificationConfig) AddFlagsWithPrefix(prefix string, flags *pflag.FlagSet) {
flags.BoolVar(&n.Enabled, prefix+".enabled", false, "Enable notification query endpoints")
addLokiFlags(&n.Loki, prefix+".loki", flags)
addLokiFlags(&n.Loki.LokiConfig, prefix+".loki", flags)
}
func (r *RuntimeConfig) AddFlagsWithPrefix(prefix string, flags *pflag.FlagSet) {

View File

@@ -24,7 +24,8 @@ func TestRuntimeConfig(t *testing.T) {
expected: RuntimeConfig{
Notification: NotificationConfig{
Enabled: false,
Loki: lokiclient.LokiConfig{
Loki: LokiConfig{
LokiConfig: lokiclient.LokiConfig{
ReadPathURL: nil,
MaxQueryLength: 721 * time.Hour,
MaxQuerySize: 65536,
@@ -32,13 +33,15 @@ func TestRuntimeConfig(t *testing.T) {
},
},
},
},
{
name: "with notification enabled",
args: []string{"--alerting.historian.notification.enabled"},
expected: RuntimeConfig{
Notification: NotificationConfig{
Enabled: true,
Loki: lokiclient.LokiConfig{
Loki: LokiConfig{
LokiConfig: lokiclient.LokiConfig{
ReadPathURL: nil,
MaxQueryLength: 721 * time.Hour,
MaxQuerySize: 65536,
@@ -46,6 +49,7 @@ func TestRuntimeConfig(t *testing.T) {
},
},
},
},
{
name: "with loki options",
args: []string{
@@ -57,7 +61,8 @@ func TestRuntimeConfig(t *testing.T) {
expected: RuntimeConfig{
Notification: NotificationConfig{
Enabled: false,
Loki: lokiclient.LokiConfig{
Loki: LokiConfig{
LokiConfig: lokiclient.LokiConfig{
ReadPathURL: lokiURL,
BasicAuthUser: "foo",
BasicAuthPassword: "bar",
@@ -68,6 +73,7 @@ func TestRuntimeConfig(t *testing.T) {
},
},
},
},
}
for _, tt := range tests {

View File

@@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
"net/http"
"regexp"
"sort"
"strings"
@@ -19,6 +20,7 @@ import (
"go.opentelemetry.io/otel/trace"
"github.com/grafana/grafana/apps/alerting/historian/pkg/apis/alertinghistorian/v0alpha1"
"github.com/grafana/grafana/apps/alerting/historian/pkg/app/config"
"github.com/grafana/grafana/apps/alerting/historian/pkg/app/logutil"
)
@@ -47,7 +49,7 @@ type LokiReader struct {
logger logging.Logger
}
func NewLokiReader(cfg lokiclient.LokiConfig, reg prometheus.Registerer, logger logging.Logger, tracer trace.Tracer) *LokiReader {
func NewLokiReader(cfg config.LokiConfig, reg prometheus.Registerer, logger logging.Logger, tracer trace.Tracer) *LokiReader {
duration := instrument.NewHistogramCollector(promauto.With(reg).NewHistogramVec(prometheus.HistogramOpts{
Namespace: Namespace,
Subsystem: Subsystem,
@@ -56,9 +58,13 @@ func NewLokiReader(cfg lokiclient.LokiConfig, reg prometheus.Registerer, logger
Buckets: instrument.DefBuckets,
}, instrument.HistogramCollectorBuckets))
requester := &http.Client{
Transport: cfg.Transport,
}
gkLogger := logutil.ToGoKitLogger(logger)
return &LokiReader{
client: lokiclient.NewLokiClient(cfg, lokiclient.NewRequester(), nil, duration, gkLogger, tracer, LokiClientSpanName),
client: lokiclient.NewLokiClient(cfg.LokiConfig, requester, nil, duration, gkLogger, tracer, LokiClientSpanName),
logger: logger,
}
}

View File

@@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/alerting/notifications
go 1.25.5
require (
github.com/grafana/grafana-app-sdk v0.48.4
github.com/grafana/grafana-app-sdk v0.48.5
github.com/grafana/grafana-app-sdk/logging v0.48.3
k8s.io/apimachinery v0.34.2
k8s.io/apiserver v0.34.2

View File

@@ -71,8 +71,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o=

View File

@@ -23,6 +23,12 @@ type Receiver struct {
Spec ReceiverSpec `json:"spec" yaml:"spec"`
}
func NewReceiver() *Receiver {
return &Receiver{
Spec: *NewReceiverSpec(),
}
}
func (o *Receiver) GetSpec() any {
return o.Spec
}

View File

@@ -12,7 +12,7 @@ import (
// schema is unexported to prevent accidental overwrites
var (
schemaReceiver = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &Receiver{}, &ReceiverList{}, resource.WithKind("Receiver"),
schemaReceiver = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", NewReceiver(), &ReceiverList{}, resource.WithKind("Receiver"),
resource.WithPlural("receivers"), resource.WithScope(resource.NamespacedScope), resource.WithSelectableFields([]resource.SelectableField{{
FieldSelector: "spec.title",
FieldValueFunc: func(o resource.Object) (string, error) {

View File

@@ -23,6 +23,12 @@ type RoutingTree struct {
Spec RoutingTreeSpec `json:"spec" yaml:"spec"`
}
func NewRoutingTree() *RoutingTree {
return &RoutingTree{
Spec: *NewRoutingTreeSpec(),
}
}
func (o *RoutingTree) GetSpec() any {
return o.Spec
}

View File

@@ -10,7 +10,7 @@ import (
// schema is unexported to prevent accidental overwrites
var (
schemaRoutingTree = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &RoutingTree{}, &RoutingTreeList{}, resource.WithKind("RoutingTree"),
schemaRoutingTree = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", NewRoutingTree(), &RoutingTreeList{}, resource.WithKind("RoutingTree"),
resource.WithPlural("routingtrees"), resource.WithScope(resource.NamespacedScope))
kindRoutingTree = resource.Kind{
Schema: schemaRoutingTree,

View File

@@ -23,6 +23,12 @@ type TemplateGroup struct {
Spec TemplateGroupSpec `json:"spec" yaml:"spec"`
}
func NewTemplateGroup() *TemplateGroup {
return &TemplateGroup{
Spec: *NewTemplateGroupSpec(),
}
}
func (o *TemplateGroup) GetSpec() any {
return o.Spec
}

View File

@@ -10,7 +10,7 @@ import (
// schema is unexported to prevent accidental overwrites
var (
schemaTemplateGroup = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &TemplateGroup{}, &TemplateGroupList{}, resource.WithKind("TemplateGroup"),
schemaTemplateGroup = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", NewTemplateGroup(), &TemplateGroupList{}, resource.WithKind("TemplateGroup"),
resource.WithPlural("templategroups"), resource.WithScope(resource.NamespacedScope))
kindTemplateGroup = resource.Kind{
Schema: schemaTemplateGroup,

View File

@@ -23,6 +23,12 @@ type TimeInterval struct {
Spec TimeIntervalSpec `json:"spec" yaml:"spec"`
}
func NewTimeInterval() *TimeInterval {
return &TimeInterval{
Spec: *NewTimeIntervalSpec(),
}
}
func (o *TimeInterval) GetSpec() any {
return o.Spec
}

View File

@@ -10,7 +10,7 @@ import (
// schema is unexported to prevent accidental overwrites
var (
schemaTimeInterval = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", &TimeInterval{}, &TimeIntervalList{}, resource.WithKind("TimeInterval"),
schemaTimeInterval = resource.NewSimpleSchema("notifications.alerting.grafana.app", "v0alpha1", NewTimeInterval(), &TimeIntervalList{}, resource.WithKind("TimeInterval"),
resource.WithPlural("timeintervals"), resource.WithScope(resource.NamespacedScope))
kindTimeInterval = resource.Kind{
Schema: schemaTimeInterval,

View File

@@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/alerting/rules
go 1.25.5
require (
github.com/grafana/grafana-app-sdk v0.48.4
github.com/grafana/grafana-app-sdk v0.48.5
github.com/grafana/grafana-app-sdk/logging v0.48.3
github.com/prometheus/common v0.67.3
k8s.io/apimachinery v0.34.2

View File

@@ -48,8 +48,8 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=

View File

@@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/annotation
go 1.25.5
require (
github.com/grafana/grafana-app-sdk v0.48.4
github.com/grafana/grafana-app-sdk v0.48.5
github.com/grafana/grafana-app-sdk/logging v0.48.3
k8s.io/apimachinery v0.34.2
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912

View File

@@ -48,8 +48,8 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=

View File

@@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/collections
go 1.25.5
require (
github.com/grafana/grafana-app-sdk v0.48.4
github.com/grafana/grafana-app-sdk v0.48.5
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250804150913-990f1c69ecc2
github.com/stretchr/testify v1.11.1
k8s.io/apimachinery v0.34.2

View File

@@ -33,8 +33,8 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250804150913-990f1c69ecc2 h1:X0cnaFdR+iz+sDSuoZmkryFSjOirchHe2MdKSRwBWgM=

View File

@@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/correlations
go 1.25.5
require (
github.com/grafana/grafana-app-sdk v0.48.4
github.com/grafana/grafana-app-sdk v0.48.5
github.com/grafana/grafana-app-sdk/logging v0.48.3
k8s.io/apimachinery v0.34.2
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912

View File

@@ -48,8 +48,8 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=

View File

@@ -11,8 +11,7 @@ do-generate: install-app-sdk update-app-sdk ## Run Grafana App SDK code generati
--tsgenpath=../../packages/grafana-schema/src/schema \
--grouping=group \
--defencoding=none \
--genoperatorstate=false \
--noschemasinmanifest
--genoperatorstate=false
.PHONY: post-generate-cleanup
post-generate-cleanup: ## Clean up the generated code

View File

@@ -5,7 +5,7 @@ go 1.25.5
require (
cuelang.org/go v0.11.1
github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4
github.com/grafana/grafana-app-sdk v0.48.4
github.com/grafana/grafana-app-sdk v0.48.5
github.com/grafana/grafana-app-sdk/logging v0.48.3
github.com/grafana/grafana-plugin-sdk-go v0.284.0
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e

View File

@@ -85,8 +85,8 @@ github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4 h1:Muoy+FMGr
github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4/go.mod h1:qeWYbnWzaYGl88JlL9+DsP1GT2Cudm58rLtx13fKZdw=
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 h1:jSojuc7njleS3UOz223WDlXOinmuLAIPI0z2vtq8EgI=
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4/go.mod h1:VahT+GtfQIM+o8ht2StR6J9g+Ef+C2Vokh5uuSmOD/4=
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
github.com/grafana/grafana-plugin-sdk-go v0.284.0 h1:1bK7eWsnPBLUWDcWJWe218Ik5ad0a5JpEL4mH9ry7Ws=

View File

@@ -25,6 +25,13 @@ type Dashboard struct {
Status DashboardStatus `json:"status" yaml:"status"`
}
func NewDashboard() *Dashboard {
return &Dashboard{
Spec: *NewDashboardSpec(),
Status: *NewDashboardStatus(),
}
}
func (o *Dashboard) GetSpec() any {
return o.Spec
}

View File

@@ -10,7 +10,7 @@ import (
// schema is unexported to prevent accidental overwrites
var (
schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v0alpha1", &Dashboard{}, &DashboardList{}, resource.WithKind("Dashboard"),
schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v0alpha1", NewDashboard(), &DashboardList{}, resource.WithKind("Dashboard"),
resource.WithPlural("dashboards"), resource.WithScope(resource.NamespacedScope))
kindDashboard = resource.Kind{
Schema: schemaDashboard,

View File

@@ -23,6 +23,12 @@ type Snapshot struct {
Spec SnapshotSpec `json:"spec" yaml:"spec"`
}
func NewSnapshot() *Snapshot {
return &Snapshot{
Spec: *NewSnapshotSpec(),
}
}
func (o *Snapshot) GetSpec() any {
return o.Spec
}

View File

@@ -10,7 +10,7 @@ import (
// schema is unexported to prevent accidental overwrites
var (
schemaSnapshot = resource.NewSimpleSchema("dashboard.grafana.app", "v0alpha1", &Snapshot{}, &SnapshotList{}, resource.WithKind("Snapshot"),
schemaSnapshot = resource.NewSimpleSchema("dashboard.grafana.app", "v0alpha1", NewSnapshot(), &SnapshotList{}, resource.WithKind("Snapshot"),
resource.WithPlural("snapshots"), resource.WithScope(resource.NamespacedScope))
kindSnapshot = resource.Kind{
Schema: schemaSnapshot,

View File

@@ -25,6 +25,13 @@ type Dashboard struct {
Status DashboardStatus `json:"status" yaml:"status"`
}
func NewDashboard() *Dashboard {
return &Dashboard{
Spec: *NewDashboardSpec(),
Status: *NewDashboardStatus(),
}
}
func (o *Dashboard) GetSpec() any {
return o.Spec
}

View File

@@ -10,7 +10,7 @@ import (
// schema is unexported to prevent accidental overwrites
var (
schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v1beta1", &Dashboard{}, &DashboardList{}, resource.WithKind("Dashboard"),
schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v1beta1", NewDashboard(), &DashboardList{}, resource.WithKind("Dashboard"),
resource.WithPlural("dashboards"), resource.WithScope(resource.NamespacedScope))
kindDashboard = resource.Kind{
Schema: schemaDashboard,

View File

@@ -25,6 +25,13 @@ type Dashboard struct {
Status DashboardStatus `json:"status" yaml:"status"`
}
func NewDashboard() *Dashboard {
return &Dashboard{
Spec: *NewDashboardSpec(),
Status: *NewDashboardStatus(),
}
}
func (o *Dashboard) GetSpec() any {
return o.Spec
}

View File

@@ -10,7 +10,7 @@ import (
// schema is unexported to prevent accidental overwrites
var (
schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v2alpha1", &Dashboard{}, &DashboardList{}, resource.WithKind("Dashboard"),
schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v2alpha1", NewDashboard(), &DashboardList{}, resource.WithKind("Dashboard"),
resource.WithPlural("dashboards"), resource.WithScope(resource.NamespacedScope))
kindDashboard = resource.Kind{
Schema: schemaDashboard,

View File

@@ -25,6 +25,13 @@ type Dashboard struct {
Status DashboardStatus `json:"status" yaml:"status"`
}
func NewDashboard() *Dashboard {
return &Dashboard{
Spec: *NewDashboardSpec(),
Status: *NewDashboardStatus(),
}
}
func (o *Dashboard) GetSpec() any {
return o.Spec
}

View File

@@ -10,7 +10,7 @@ import (
// schema is unexported to prevent accidental overwrites
var (
schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v2beta1", &Dashboard{}, &DashboardList{}, resource.WithKind("Dashboard"),
schemaDashboard = resource.NewSimpleSchema("dashboard.grafana.app", "v2beta1", NewDashboard(), &DashboardList{}, resource.WithKind("Dashboard"),
resource.WithPlural("dashboards"), resource.WithScope(resource.NamespacedScope))
kindDashboard = resource.Kind{
Schema: schemaDashboard,

File diff suppressed because one or more lines are too long

View File

@@ -7234,9 +7234,9 @@
"type": "elasticsearch",
"uid": "gdev-elasticsearch"
},
"baseFilters": null,
"baseFilters": [],
"filters": [],
"defaultKeys": null,
"defaultKeys": [],
"hide": "dontHide",
"skipUrlSync": false,
"allowCustomValue": true

View File

@@ -7335,9 +7335,9 @@
},
"spec": {
"name": "adhoc",
"baseFilters": null,
"baseFilters": [],
"filters": [],
"defaultKeys": null,
"defaultKeys": [],
"hide": "dontHide",
"skipUrlSync": false,
"allowCustomValue": true

View File

@@ -307,9 +307,9 @@
"kind": "AdhocVariable",
"spec": {
"name": "adhoc",
"baseFilters": null,
"baseFilters": [],
"filters": [],
"defaultKeys": null,
"defaultKeys": [],
"hide": "dontHide",
"skipUrlSync": false,
"allowCustomValue": true

View File

@@ -317,9 +317,9 @@
"datasource": {},
"spec": {
"name": "adhoc",
"baseFilters": null,
"baseFilters": [],
"filters": [],
"defaultKeys": null,
"defaultKeys": [],
"hide": "dontHide",
"skipUrlSync": false,
"allowCustomValue": true

View File

@@ -604,9 +604,9 @@
"type": "loki",
"uid": "PDDA8E780A17E7EF1"
},
"baseFilters": null,
"baseFilters": [],
"filters": [],
"defaultKeys": null,
"defaultKeys": [],
"label": "Ad-hoc",
"hide": "dontHide",
"skipUrlSync": false,

View File

@@ -616,9 +616,9 @@
},
"spec": {
"name": "adhoc",
"baseFilters": null,
"baseFilters": [],
"filters": [],
"defaultKeys": null,
"defaultKeys": [],
"label": "Ad-hoc",
"hide": "dontHide",
"skipUrlSync": false,

View File

@@ -1885,7 +1885,7 @@
"name": "Filters",
"baseFilters": [],
"filters": [],
"defaultKeys": null,
"defaultKeys": [],
"hide": "dontHide",
"skipUrlSync": false,
"allowCustomValue": true

View File

@@ -1931,7 +1931,7 @@
"name": "Filters",
"baseFilters": [],
"filters": [],
"defaultKeys": null,
"defaultKeys": [],
"hide": "dontHide",
"skipUrlSync": false,
"allowCustomValue": true

View File

@@ -2184,7 +2184,7 @@
"name": "Filters",
"baseFilters": [],
"filters": [],
"defaultKeys": null,
"defaultKeys": [],
"hide": "dontHide",
"skipUrlSync": false,
"allowCustomValue": true

View File

@@ -2219,7 +2219,7 @@
"name": "Filters",
"baseFilters": [],
"filters": [],
"defaultKeys": null,
"defaultKeys": [],
"hide": "dontHide",
"skipUrlSync": false,
"allowCustomValue": true

View File

@@ -2499,7 +2499,7 @@
"name": "Filters",
"baseFilters": [],
"filters": [],
"defaultKeys": null,
"defaultKeys": [],
"hide": "dontHide",
"skipUrlSync": false,
"allowCustomValue": true

View File

@@ -2542,7 +2542,7 @@
"name": "Filters",
"baseFilters": [],
"filters": [],
"defaultKeys": null,
"defaultKeys": [],
"hide": "dontHide",
"skipUrlSync": false,
"allowCustomValue": true

View File

@@ -1539,26 +1539,38 @@ func buildAdhocVariable(ctx context.Context, varMap map[string]interface{}, comm
},
}
// Transform baseFilters if they exist
// Transform baseFilters if they exist, otherwise default to empty array
if baseFilters, exists := varMap["baseFilters"]; exists {
if baseFiltersArray, ok := baseFilters.([]interface{}); ok {
adhocVar.Spec.BaseFilters = transformAdHocFilters(baseFiltersArray)
}
}
// Ensure baseFilters is always set (default to empty array if not present or invalid)
if adhocVar.Spec.BaseFilters == nil {
adhocVar.Spec.BaseFilters = []dashv2alpha1.DashboardAdHocFilterWithLabels{}
}
// Transform filters if they exist
// Transform filters if they exist, otherwise default to empty array
if filters, exists := varMap["filters"]; exists {
if filtersArray, ok := filters.([]interface{}); ok {
adhocVar.Spec.Filters = transformAdHocFilters(filtersArray)
}
}
// Ensure filters is always set (default to empty array if not present or invalid)
if adhocVar.Spec.Filters == nil {
adhocVar.Spec.Filters = []dashv2alpha1.DashboardAdHocFilterWithLabels{}
}
// Transform defaultKeys if they exist
// Transform defaultKeys if they exist, otherwise default to empty array
if defaultKeys, exists := varMap["defaultKeys"]; exists {
if defaultKeysArray, ok := defaultKeys.([]interface{}); ok {
adhocVar.Spec.DefaultKeys = transformMetricFindValues(defaultKeysArray)
}
}
// Ensure defaultKeys is always set (default to empty array if not present or invalid)
if adhocVar.Spec.DefaultKeys == nil {
adhocVar.Spec.DefaultKeys = []dashv2alpha1.DashboardMetricFindValue{}
}
// Only include datasource if datasourceUID exists (matching frontend behavior)
if datasourceUID != "" {

View File

@@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/example
go 1.25.5
require (
github.com/grafana/grafana-app-sdk v0.48.4
github.com/grafana/grafana-app-sdk v0.48.5
github.com/grafana/grafana-app-sdk/logging v0.48.3
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20251017153501-8512b219c5fe
k8s.io/apimachinery v0.34.2

View File

@@ -56,8 +56,8 @@ github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4 h1:Muoy+FMGr
github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4/go.mod h1:qeWYbnWzaYGl88JlL9+DsP1GT2Cudm58rLtx13fKZdw=
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 h1:jSojuc7njleS3UOz223WDlXOinmuLAIPI0z2vtq8EgI=
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4/go.mod h1:VahT+GtfQIM+o8ht2StR6J9g+Ef+C2Vokh5uuSmOD/4=
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20251017153501-8512b219c5fe h1:pPoFj2bQKDBg5EyEdOU+Jn+0hQN+M775Qihk73RbdSs=

View File

@@ -3,42 +3,67 @@ module github.com/grafana/grafana/apps/folder
go 1.25.5
require (
github.com/grafana/grafana-app-sdk v0.48.4
github.com/grafana/grafana-app-sdk v0.48.5
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e
k8s.io/apimachinery v0.34.2
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912
)
require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/getkin/kin-openapi v0.133.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-openapi/jsonpointer v0.22.1 // indirect
github.com/go-openapi/jsonreference v0.21.2 // indirect
github.com/go-openapi/swag v0.23.1 // indirect
github.com/go-openapi/swag/jsonname v0.25.1 // indirect
github.com/go-test/deep v1.1.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/gnostic-models v0.7.0 // indirect
github.com/grafana/grafana-app-sdk/logging v0.48.3 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.9.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.23.2 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.67.3 // indirect
github.com/prometheus/procfs v0.16.1 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/stretchr/testify v1.11.1 // indirect
github.com/woodsbury/decimal128 v1.3.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.opentelemetry.io/otel v1.38.0 // indirect
go.opentelemetry.io/otel/trace v1.38.0 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/net v0.47.0 // indirect
golang.org/x/oauth2 v0.33.0 // indirect
golang.org/x/sys v0.38.0 // indirect
golang.org/x/term v0.37.0 // indirect
golang.org/x/text v0.31.0 // indirect
golang.org/x/time v0.14.0 // indirect
google.golang.org/protobuf v1.36.10 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/client-go v0.34.2 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.1 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect
)

View File

@@ -1,3 +1,7 @@
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
@@ -6,6 +10,8 @@ github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bF
github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/getkin/kin-openapi v0.133.0 h1:pJdmNohVIJ97r4AUFtEXRXwESr8b0bD721u/Tz6k8PQ=
github.com/getkin/kin-openapi v0.133.0/go.mod h1:boAciF6cXk5FhPqe/NQeBTeenbjqU4LhWBf09ILVvWE=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-openapi/jsonpointer v0.22.1 h1:sHYI1He3b9NqJ4wXLoJDKmUmHkWy/L7rtEo92JUxBNk=
@@ -16,6 +22,8 @@ github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZ
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
github.com/go-openapi/swag/jsonname v0.25.1 h1:Sgx+qbwa4ej6AomWC6pEfXrA6uP2RkaNjA9BR8a1RJU=
github.com/go-openapi/swag/jsonname v0.25.1/go.mod h1:71Tekow6UOLBD3wS7XhdT98g5J5GR13NOTQ9/6Q11Zo=
github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
@@ -23,20 +31,33 @@ github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7O
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e h1:BTKk7LHuG1kmAkucwTA7DuMbKpKvJTKrGdBmUNO4dfQ=
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250514132646-acbc7b54ed9e/go.mod h1:IA4SOwun8QyST9c5UNs/fN37XL6boXXDvRYFcFwbipg=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -45,9 +66,29 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY=
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw=
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c=
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o=
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.67.3 h1:shd26MlnwTw5jksTDhC7rTQIteBxy+ZZDr3t7F2xN2Q=
github.com/prometheus/common v0.67.3/go.mod h1:gP0fq6YjjNCLssJCQp0yk4M8W6ikLURwkdd/YKtTbyI=
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
@@ -58,10 +99,20 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/woodsbury/decimal128 v1.3.0 h1:8pffMNWIlC0O5vbyHWFZAt5yWvWcrHA+3ovIIjVWss0=
github.com/woodsbury/decimal128 v1.3.0/go.mod h1:C5UTmyTjW3JftjUFzOVhC20BEQa2a4ZKOB5I6Zjb+ds=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
@@ -77,16 +128,24 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
@@ -100,12 +159,18 @@ google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.34.2 h1:fsSUNZhV+bnL6Aqrp6O7lMTy6o5x2C4XLjnh//8SLYY=
k8s.io/api v0.34.2/go.mod h1:MMBPaWlED2a8w4RSeanD76f7opUoypY8TFYkSM+3XHw=
k8s.io/apimachinery v0.34.2 h1:zQ12Uk3eMHPxrsbUJgNF8bTauTVR2WgqJsTmwTE/NW4=
k8s.io/apimachinery v0.34.2/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw=
k8s.io/client-go v0.34.2 h1:Co6XiknN+uUZqiddlfAjT68184/37PS4QAzYvQvDR8M=
k8s.io/client-go v0.34.2/go.mod h1:2VYDl1XXJsdcAxw7BenFslRQX28Dxz91U9MWKjX97fE=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE=

View File

@@ -23,6 +23,12 @@ type Folder struct {
Spec FolderSpec `json:"spec" yaml:"spec"`
}
func NewFolder() *Folder {
return &Folder{
Spec: *NewFolderSpec(),
}
}
func (o *Folder) GetSpec() any {
return o.Spec
}

View File

@@ -10,7 +10,7 @@ import (
// schema is unexported to prevent accidental overwrites
var (
schemaFolder = resource.NewSimpleSchema("folder.grafana.app", "v1beta1", &Folder{}, &FolderList{}, resource.WithKind("Folder"),
schemaFolder = resource.NewSimpleSchema("folder.grafana.app", "v1beta1", NewFolder(), &FolderList{}, resource.WithKind("Folder"),
resource.WithPlural("folders"), resource.WithScope(resource.NamespacedScope))
kindFolder = resource.Kind{
Schema: schemaFolder,

View File

@@ -0,0 +1,116 @@
//
// This file is generated by grafana-app-sdk
// DO NOT EDIT
//
package manifestdata
import (
"fmt"
"strings"
"github.com/grafana/grafana-app-sdk/app"
"github.com/grafana/grafana-app-sdk/resource"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/kube-openapi/pkg/spec3"
"k8s.io/kube-openapi/pkg/validation/spec"
v1beta1 "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
)
var appManifestData = app.ManifestData{
AppName: "folder",
Group: "folder.grafana.app",
PreferredVersion: "v1beta1",
Versions: []app.ManifestVersion{
{
Name: "v1beta1",
Served: true,
Kinds: []app.ManifestVersionKind{
{
Kind: "Folder",
Plural: "Folders",
Scope: "Namespaced",
Conversion: false,
},
},
Routes: app.ManifestVersionRoutes{
Namespaced: map[string]spec3.PathProps{},
Cluster: map[string]spec3.PathProps{},
Schemas: map[string]spec.Schema{},
},
},
},
}
func LocalManifest() app.Manifest {
return app.NewEmbeddedManifest(appManifestData)
}
func RemoteManifest() app.Manifest {
return app.NewAPIServerManifest("folder")
}
var kindVersionToGoType = map[string]resource.Kind{
"Folder/v1beta1": v1beta1.FolderKind(),
}
// ManifestGoTypeAssociator returns the associated resource.Kind instance for a given Kind and Version, if one exists.
// If there is no association for the provided Kind and Version, exists will return false.
func ManifestGoTypeAssociator(kind, version string) (goType resource.Kind, exists bool) {
goType, exists = kindVersionToGoType[fmt.Sprintf("%s/%s", kind, version)]
return goType, exists
}
var customRouteToGoResponseType = map[string]any{}
// ManifestCustomRouteResponsesAssociator returns the associated response go type for a given kind, version, custom route path, and method, if one exists.
// kind may be empty for custom routes which are not kind subroutes. Leading slashes are removed from subroute paths.
// If there is no association for the provided kind, version, custom route path, and method, exists will return false.
// Resource routes (those without a kind) should prefix their route with "<namespace>/" if the route is namespaced (otherwise the route is assumed to be cluster-scope)
func ManifestCustomRouteResponsesAssociator(kind, version, path, verb string) (goType any, exists bool) {
if len(path) > 0 && path[0] == '/' {
path = path[1:]
}
goType, exists = customRouteToGoResponseType[fmt.Sprintf("%s|%s|%s|%s", version, kind, path, strings.ToUpper(verb))]
return goType, exists
}
var customRouteToGoParamsType = map[string]runtime.Object{}
func ManifestCustomRouteQueryAssociator(kind, version, path, verb string) (goType runtime.Object, exists bool) {
if len(path) > 0 && path[0] == '/' {
path = path[1:]
}
goType, exists = customRouteToGoParamsType[fmt.Sprintf("%s|%s|%s|%s", version, kind, path, strings.ToUpper(verb))]
return goType, exists
}
var customRouteToGoRequestBodyType = map[string]any{}
func ManifestCustomRouteRequestBodyAssociator(kind, version, path, verb string) (goType any, exists bool) {
if len(path) > 0 && path[0] == '/' {
path = path[1:]
}
goType, exists = customRouteToGoRequestBodyType[fmt.Sprintf("%s|%s|%s|%s", version, kind, path, strings.ToUpper(verb))]
return goType, exists
}
type GoTypeAssociator struct{}
func NewGoTypeAssociator() *GoTypeAssociator {
return &GoTypeAssociator{}
}
func (g *GoTypeAssociator) KindToGoType(kind, version string) (goType resource.Kind, exists bool) {
return ManifestGoTypeAssociator(kind, version)
}
func (g *GoTypeAssociator) CustomRouteReturnGoType(kind, version, path, verb string) (goType any, exists bool) {
return ManifestCustomRouteResponsesAssociator(kind, version, path, verb)
}
func (g *GoTypeAssociator) CustomRouteQueryGoType(kind, version, path, verb string) (goType runtime.Object, exists bool) {
return ManifestCustomRouteQueryAssociator(kind, version, path, verb)
}
func (g *GoTypeAssociator) CustomRouteRequestBodyGoType(kind, version, path, verb string) (goType any, exists bool) {
return ManifestCustomRouteRequestBodyAssociator(kind, version, path, verb)
}

View File

@@ -52,7 +52,7 @@ replace github.com/prometheus/alertmanager => github.com/grafana/prometheus-aler
require (
github.com/grafana/grafana v0.0.0-00010101000000-000000000000
github.com/grafana/grafana-app-sdk v0.48.4
github.com/grafana/grafana-app-sdk v0.48.5
github.com/grafana/grafana-app-sdk/logging v0.48.3
github.com/grafana/grafana/apps/folder v0.0.0
github.com/grafana/grafana/pkg/apimachinery v0.0.0

View File

@@ -835,8 +835,8 @@ github.com/grafana/gofpdf v0.0.0-20250307124105-3b9c5d35577f h1:5xkjl5Y/j2QefJKO
github.com/grafana/gofpdf v0.0.0-20250307124105-3b9c5d35577f/go.mod h1:+O5QxOwwgP10jedZHapzXY+IPKTnzHBtIs5UUb9G+kI=
github.com/grafana/gomemcache v0.0.0-20250828162811-a96f6acee2fe h1:q+QaVANzNZxvTovycpQvDTfsNZ2rHh4XIIaccMnrIR4=
github.com/grafana/gomemcache v0.0.0-20250828162811-a96f6acee2fe/go.mod h1:j/s0jkda4UXTemDs7Pgw/vMT06alWc42CHisvYac0qw=
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
github.com/grafana/grafana-aws-sdk v1.3.0 h1:/bfJzP93rCel1GbWoRSq0oUo424MZXt8jAp2BK9w8tM=

View File

@@ -22,4 +22,32 @@ v0alpha1: {
serviceaccountv0alpha1,
externalGroupMappingv0alpha1
]
routes: {
namespaced: {
"/searchTeams": {
"GET": {
request: {
query: {
query?: string
}
}
response: {
#TeamHit: {
name: string
title: string
email: string
provisioned: bool
externalUID: string
}
offset: int64
totalHits: int64
hits: [...#TeamHit]
queryCost: float64
maxScore: float64
}
responseMetadata: objectMeta: false
}
}
}
}
}

View File

@@ -0,0 +1,33 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v0alpha1
import (
"github.com/grafana/grafana-app-sdk/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
type GetSearchTeamsRequestParamsObject struct {
metav1.TypeMeta `json:",inline"`
GetSearchTeamsRequestParams `json:",inline"`
}
func NewGetSearchTeamsRequestParamsObject() *GetSearchTeamsRequestParamsObject {
return &GetSearchTeamsRequestParamsObject{}
}
func (o *GetSearchTeamsRequestParamsObject) DeepCopyObject() runtime.Object {
dst := NewGetSearchTeamsRequestParamsObject()
o.DeepCopyInto(dst)
return dst
}
func (o *GetSearchTeamsRequestParamsObject) DeepCopyInto(dst *GetSearchTeamsRequestParamsObject) {
dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion
dst.TypeMeta.Kind = o.TypeMeta.Kind
dstGetSearchTeamsRequestParams := GetSearchTeamsRequestParams{}
_ = resource.CopyObjectInto(&dstGetSearchTeamsRequestParams, &o.GetSearchTeamsRequestParams)
}
var _ runtime.Object = NewGetSearchTeamsRequestParamsObject()

View File

@@ -0,0 +1,12 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v0alpha1
type GetSearchTeamsRequestParams struct {
Query *string `json:"query,omitempty"`
}
// NewGetSearchTeamsRequestParams creates a new GetSearchTeamsRequestParams object.
func NewGetSearchTeamsRequestParams() *GetSearchTeamsRequestParams {
return &GetSearchTeamsRequestParams{}
}

View File

@@ -0,0 +1,33 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v0alpha1
// +k8s:openapi-gen=true
type VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit struct {
Name string `json:"name"`
Title string `json:"title"`
Email string `json:"email"`
Provisioned bool `json:"provisioned"`
ExternalUID string `json:"externalUID"`
}
// NewVersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit creates a new VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit object.
func NewVersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit() *VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit {
return &VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit{}
}
// +k8s:openapi-gen=true
type GetSearchTeamsBody struct {
Offset int64 `json:"offset"`
TotalHits int64 `json:"totalHits"`
Hits []VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit `json:"hits"`
QueryCost float64 `json:"queryCost"`
MaxScore float64 `json:"maxScore"`
}
// NewGetSearchTeamsBody creates a new GetSearchTeamsBody object.
func NewGetSearchTeamsBody() *GetSearchTeamsBody {
return &GetSearchTeamsBody{
Hits: []VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit{},
}
}

View File

@@ -0,0 +1,37 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
package v0alpha1
import (
"github.com/grafana/grafana-app-sdk/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
// +k8s:openapi-gen=true
type GetSearchTeams struct {
metav1.TypeMeta `json:",inline"`
GetSearchTeamsBody `json:",inline"`
}
func NewGetSearchTeams() *GetSearchTeams {
return &GetSearchTeams{}
}
func (t *GetSearchTeamsBody) DeepCopyInto(dst *GetSearchTeamsBody) {
_ = resource.CopyObjectInto(dst, t)
}
func (o *GetSearchTeams) DeepCopyObject() runtime.Object {
dst := NewGetSearchTeams()
o.DeepCopyInto(dst)
return dst
}
func (o *GetSearchTeams) DeepCopyInto(dst *GetSearchTeams) {
dst.TypeMeta.APIVersion = o.TypeMeta.APIVersion
dst.TypeMeta.Kind = o.TypeMeta.Kind
o.GetSearchTeamsBody.DeepCopyInto(&dst.GetSearchTeamsBody)
}
var _ runtime.Object = NewGetSearchTeams()

View File

@@ -317,6 +317,7 @@ func AddAuthNKnownTypes(scheme *runtime.Scheme) error {
&ServiceAccountList{},
&Team{},
&TeamList{},
&GetSearchTeams{},
&TeamBinding{},
&TeamBindingList{},
&ExternalGroupMapping{},

View File

@@ -0,0 +1,35 @@
package v0alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +k8s:deepcopy-gen=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type TeamSearchResults struct {
metav1.TypeMeta `json:",inline"`
// Where the query started from
Offset int64 `json:"offset,omitempty"`
// The number of matching results
TotalHits int64 `json:"totalHits"`
// The team body
Hits []TeamHit `json:"hits"`
// Cost of running the query
QueryCost float64 `json:"queryCost,omitempty"`
// Max score
MaxScore float64 `json:"maxScore,omitempty"`
}
// +k8s:deepcopy-gen=true
type TeamHit struct {
Name string `json:"name"`
Title string `json:"title"`
Email string `json:"email,omitempty"`
Provisioned bool `json:"provisioned,omitempty"`
ExternalUID string `json:"externalUID,omitempty"`
}

View File

@@ -24,6 +24,8 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.ExternalGroupMappingTeamRef": schema_pkg_apis_iam_v0alpha1_ExternalGroupMappingTeamRef(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GetGroups": schema_pkg_apis_iam_v0alpha1_GetGroups(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GetGroupsBody": schema_pkg_apis_iam_v0alpha1_GetGroupsBody(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GetSearchTeams": schema_pkg_apis_iam_v0alpha1_GetSearchTeams(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GetSearchTeamsBody": schema_pkg_apis_iam_v0alpha1_GetSearchTeamsBody(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRole": schema_pkg_apis_iam_v0alpha1_GlobalRole(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleBinding": schema_pkg_apis_iam_v0alpha1_GlobalRoleBinding(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.GlobalRoleBindingList": schema_pkg_apis_iam_v0alpha1_GlobalRoleBindingList(ref),
@@ -80,6 +82,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserStatus": schema_pkg_apis_iam_v0alpha1_UserStatus(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.UserstatusOperatorState": schema_pkg_apis_iam_v0alpha1_UserstatusOperatorState(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.VersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping": schema_pkg_apis_iam_v0alpha1_VersionsV0alpha1Kinds7RoutesGroupsGETResponseExternalGroupMapping(ref),
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit": schema_pkg_apis_iam_v0alpha1_VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit(ref),
}
}
@@ -564,6 +567,132 @@ func schema_pkg_apis_iam_v0alpha1_GetGroupsBody(ref common.ReferenceCallback) co
}
}
func schema_pkg_apis_iam_v0alpha1_GetSearchTeams(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"kind": {
SchemaProps: spec.SchemaProps{
Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
Type: []string{"string"},
Format: "",
},
},
"apiVersion": {
SchemaProps: spec.SchemaProps{
Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
Type: []string{"string"},
Format: "",
},
},
"offset": {
SchemaProps: spec.SchemaProps{
Default: 0,
Type: []string{"integer"},
Format: "int64",
},
},
"totalHits": {
SchemaProps: spec.SchemaProps{
Default: 0,
Type: []string{"integer"},
Format: "int64",
},
},
"hits": {
SchemaProps: spec.SchemaProps{
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit"),
},
},
},
},
},
"queryCost": {
SchemaProps: spec.SchemaProps{
Default: 0,
Type: []string{"number"},
Format: "double",
},
},
"maxScore": {
SchemaProps: spec.SchemaProps{
Default: 0,
Type: []string{"number"},
Format: "double",
},
},
},
Required: []string{"offset", "totalHits", "hits", "queryCost", "maxScore"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit"},
}
}
func schema_pkg_apis_iam_v0alpha1_GetSearchTeamsBody(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"offset": {
SchemaProps: spec.SchemaProps{
Default: 0,
Type: []string{"integer"},
Format: "int64",
},
},
"totalHits": {
SchemaProps: spec.SchemaProps{
Default: 0,
Type: []string{"integer"},
Format: "int64",
},
},
"hits": {
SchemaProps: spec.SchemaProps{
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit"),
},
},
},
},
},
"queryCost": {
SchemaProps: spec.SchemaProps{
Default: 0,
Type: []string{"number"},
Format: "double",
},
},
"maxScore": {
SchemaProps: spec.SchemaProps{
Default: 0,
Type: []string{"number"},
Format: "double",
},
},
},
Required: []string{"offset", "totalHits", "hits", "queryCost", "maxScore"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit"},
}
}
func schema_pkg_apis_iam_v0alpha1_GlobalRole(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -2956,3 +3085,51 @@ func schema_pkg_apis_iam_v0alpha1_VersionsV0alpha1Kinds7RoutesGroupsGETResponseE
},
}
}
func schema_pkg_apis_iam_v0alpha1_VersionsV0alpha1RoutesNamespacedSearchTeamsGETResponseTeamHit(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"name": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"title": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"email": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"provisioned": {
SchemaProps: spec.SchemaProps{
Default: false,
Type: []string{"boolean"},
Format: "",
},
},
"externalUID": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"name", "title", "email", "provisioned", "externalUID"},
},
},
}
}

View File

@@ -157,9 +157,139 @@ var appManifestData = app.ManifestData{
},
},
Routes: app.ManifestVersionRoutes{
Namespaced: map[string]spec3.PathProps{},
Namespaced: map[string]spec3.PathProps{
"/searchTeams": {
Get: &spec3.Operation{
OperationProps: spec3.OperationProps{
OperationId: "getSearchTeams",
Parameters: []*spec3.Parameter{
{
ParameterProps: spec3.ParameterProps{
Name: "query",
In: "query",
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
},
},
},
},
},
Responses: &spec3.Responses{
ResponsesProps: spec3.ResponsesProps{
Default: &spec3.Response{
ResponseProps: spec3.ResponseProps{
Description: "Default OK response",
Content: map[string]*spec3.MediaType{
"application/json": {
MediaTypeProps: spec3.MediaTypeProps{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"apiVersion": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
},
},
"hits": {
SchemaProps: spec.SchemaProps{
Type: []string{"array"},
},
},
"kind": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
},
},
"maxScore": {
SchemaProps: spec.SchemaProps{
Type: []string{"number"},
},
},
"offset": {
SchemaProps: spec.SchemaProps{
Type: []string{"integer"},
},
},
"queryCost": {
SchemaProps: spec.SchemaProps{
Type: []string{"number"},
},
},
"totalHits": {
SchemaProps: spec.SchemaProps{
Type: []string{"integer"},
},
},
},
Required: []string{
"offset",
"totalHits",
"hits",
"queryCost",
"maxScore",
"apiVersion",
"kind",
},
}},
}},
},
},
},
}},
},
},
},
},
Cluster: map[string]spec3.PathProps{},
Schemas: map[string]spec.Schema{},
Schemas: map[string]spec.Schema{
"getSearchTeamsTeamHit": {
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"email": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
},
},
"externalUID": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
},
},
"name": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
},
},
"provisioned": {
SchemaProps: spec.SchemaProps{
Type: []string{"boolean"},
},
},
"title": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
},
},
},
Required: []string{
"name",
"title",
"email",
"provisioned",
"externalUID",
},
},
},
},
},
},
},
@@ -196,6 +326,8 @@ func ManifestGoTypeAssociator(kind, version string) (goType resource.Kind, exist
var customRouteToGoResponseType = map[string]any{
"v0alpha1|Team|groups|GET": v0alpha1.GetGroups{},
"v0alpha1||<namespace>/searchTeams|GET": v0alpha1.GetSearchTeams{},
}
// ManifestCustomRouteResponsesAssociator returns the associated response go type for a given kind, version, custom route path, and method, if one exists.

View File

@@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/investigations
go 1.25.5
require (
github.com/grafana/grafana-app-sdk v0.48.4
github.com/grafana/grafana-app-sdk v0.48.5
k8s.io/apimachinery v0.34.2
k8s.io/klog/v2 v2.130.1
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912

View File

@@ -48,8 +48,8 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=

View File

@@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/logsdrilldown
go 1.25.5
require (
github.com/grafana/grafana-app-sdk v0.48.4
github.com/grafana/grafana-app-sdk v0.48.5
github.com/grafana/grafana-app-sdk/logging v0.48.3
k8s.io/apimachinery v0.34.2
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912

View File

@@ -48,8 +48,8 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=

View File

@@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/playlist
go 1.25.5
require (
github.com/grafana/grafana-app-sdk v0.48.4
github.com/grafana/grafana-app-sdk v0.48.5
k8s.io/apimachinery v0.34.2
k8s.io/client-go v0.34.2
k8s.io/klog/v2 v2.130.1

View File

@@ -48,8 +48,8 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=

View File

@@ -10,8 +10,9 @@ replace github.com/grafana/grafana/pkg/apiserver => ../../pkg/apiserver
require (
github.com/emicklei/go-restful/v3 v3.13.0
github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4
github.com/grafana/grafana v0.0.0-00010101000000-000000000000
github.com/grafana/grafana-app-sdk v0.48.4
github.com/grafana/grafana-app-sdk v0.48.5
github.com/grafana/grafana-app-sdk/logging v0.48.3
github.com/grafana/grafana/pkg/apimachinery v0.0.0
github.com/stretchr/testify v1.11.1
@@ -59,7 +60,7 @@ require (
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.22.1 // indirect
github.com/go-openapi/jsonreference v0.21.2 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-openapi/swag v0.23.1 // indirect
github.com/go-openapi/swag/jsonname v0.25.1 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/go-test/deep v1.1.1 // indirect
@@ -75,9 +76,8 @@ require (
github.com/google/gnostic-models v0.7.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/grafana/alerting v0.0.0-20251119204204-77fa75125181 // indirect
github.com/grafana/alerting v0.0.0-20251204145817-de8c2bbf9eba // indirect
github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f // indirect
github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4 // indirect
github.com/grafana/dataplane/sdata v0.0.9 // indirect
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 // indirect
github.com/grafana/grafana-aws-sdk v1.3.0 // indirect
@@ -142,7 +142,7 @@ require (
github.com/pierrec/lz4/v4 v4.1.22 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/alertmanager v0.28.0 // indirect
github.com/prometheus/alertmanager v0.28.2 // indirect
github.com/prometheus/client_golang v1.23.2 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.67.3 // indirect
@@ -194,8 +194,8 @@ require (
golang.org/x/tools v0.39.0 // indirect
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba // indirect
google.golang.org/grpc v1.77.0 // indirect
google.golang.org/protobuf v1.36.10 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
@@ -215,3 +215,6 @@ require (
sigs.k8s.io/structured-merge-diff/v6 v6.3.1 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect
)
// Use our fork of the upstream Alertmanager.
replace github.com/prometheus/alertmanager => github.com/grafana/prometheus-alertmanager v0.25.1-0.20250911094103-5456b6e45604

View File

@@ -110,8 +110,8 @@ github.com/go-openapi/jsonpointer v0.22.1 h1:sHYI1He3b9NqJ4wXLoJDKmUmHkWy/L7rtEo
github.com/go-openapi/jsonpointer v0.22.1/go.mod h1:pQT9OsLkfz1yWoMgYFy4x3U5GY5nUlsOn1qSBH5MkCM=
github.com/go-openapi/jsonreference v0.21.2 h1:Wxjda4M/BBQllegefXrY/9aq1fxBA8sI5M/lFU6tSWU=
github.com/go-openapi/jsonreference v0.21.2/go.mod h1:pp3PEjIsJ9CZDGCNOyXIQxsNuroxm8FAJ/+quA0yKzQ=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
github.com/go-openapi/swag/jsonname v0.25.1 h1:Sgx+qbwa4ej6AomWC6pEfXrA6uP2RkaNjA9BR8a1RJU=
github.com/go-openapi/swag/jsonname v0.25.1/go.mod h1:71Tekow6UOLBD3wS7XhdT98g5J5GR13NOTQ9/6Q11Zo=
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
@@ -174,8 +174,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
github.com/grafana/alerting v0.0.0-20251119204204-77fa75125181 h1:nbxKRtrbuhvOYmI2RhOYauHRJCtpR+vTNIgg1lFUCws=
github.com/grafana/alerting v0.0.0-20251119204204-77fa75125181/go.mod h1:VtPNIFlEOJPPEc13Ax6ZTbNV3M/sAzLID72YjgzOPVA=
github.com/grafana/alerting v0.0.0-20251204145817-de8c2bbf9eba h1:psKWNETD5nGxmFAlqnWsXoRyUwSa2GHNEMSEDKGKfQ4=
github.com/grafana/alerting v0.0.0-20251204145817-de8c2bbf9eba/go.mod h1:l7v67cgP7x72ajB9UPZlumdrHqNztpKoqQ52cU8T3LU=
github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f h1:Cbm6OKkOcJ+7CSZsGsEJzktC/SIa5bxVeYKQLuYK86o=
github.com/grafana/authlib v0.0.0-20250930082137-a40e2c2b094f/go.mod h1:axY0cdOg3q0TZHwpHnIz5x16xZ8ZBxJHShsSHHXcHQg=
github.com/grafana/authlib/types v0.0.0-20251119142549-be091cf2f4d4 h1:Muoy+FMGrHj3GdFbvsMzUT7eusgii9PKf9L1ZaXDDbY=
@@ -184,8 +184,8 @@ github.com/grafana/dataplane/sdata v0.0.9 h1:AGL1LZnCUG4MnQtnWpBPbQ8ZpptaZs14w6k
github.com/grafana/dataplane/sdata v0.0.9/go.mod h1:Jvs5ddpGmn6vcxT7tCTWAZ1mgi4sbcdFt9utQx5uMAU=
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4 h1:jSojuc7njleS3UOz223WDlXOinmuLAIPI0z2vtq8EgI=
github.com/grafana/dskit v0.0.0-20250908063411-6b6da59b5cc4/go.mod h1:VahT+GtfQIM+o8ht2StR6J9g+Ef+C2Vokh5uuSmOD/4=
github.com/grafana/grafana-app-sdk v0.48.4 h1:t9r+Y6E7D832ZxQ2c1n0lp6cvsYKhhrAodVYzE1y0s0=
github.com/grafana/grafana-app-sdk v0.48.4/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk v0.48.5 h1:MS8l9fTZz+VbTfgApn09jw27GxhQ6fNOWGhC4ydvZmM=
github.com/grafana/grafana-app-sdk v0.48.5/go.mod h1:HJsMOSBmt/D/Ihs1SvagOwmXKi0coBMVHlfvdd+qe9Y=
github.com/grafana/grafana-app-sdk/logging v0.48.3 h1:72NUpGNiJXCNQz/on++YSsl38xuVYYBKv5kKQaOClX4=
github.com/grafana/grafana-app-sdk/logging v0.48.3/go.mod h1:Gh/nBWnspK3oDNWtiM5qUF/fardHzOIEez+SPI3JeHA=
github.com/grafana/grafana-aws-sdk v1.3.0 h1:/bfJzP93rCel1GbWoRSq0oUo424MZXt8jAp2BK9w8tM=
@@ -196,6 +196,8 @@ github.com/grafana/grafana-plugin-sdk-go v0.284.0 h1:1bK7eWsnPBLUWDcWJWe218Ik5ad
github.com/grafana/grafana-plugin-sdk-go v0.284.0/go.mod h1:lHPniaSxq3SL5MxDIPy04TYB1jnTp/ivkYO+xn5Rz3E=
github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8=
github.com/grafana/otel-profiling-go v0.5.1/go.mod h1:ftN/t5A/4gQI19/8MoWurBEtC6gFw8Dns1sJZ9W4Tls=
github.com/grafana/prometheus-alertmanager v0.25.1-0.20250911094103-5456b6e45604 h1:aXfUhVN/Ewfpbko2CCtL65cIiGgwStOo4lWH2b6gw2U=
github.com/grafana/prometheus-alertmanager v0.25.1-0.20250911094103-5456b6e45604/go.mod h1:O/QP1BCm0HHIzbKvgMzqb5sSyH88rzkFk84F4TfJjBU=
github.com/grafana/pyroscope-go/godeltaprof v0.1.9 h1:c1Us8i6eSmkW+Ez05d3co8kasnuOY813tbMN8i/a3Og=
github.com/grafana/pyroscope-go/godeltaprof v0.1.9/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU=
github.com/grafana/sqlds/v4 v4.2.7 h1:sFQhsS7DBakNMdxa++yOfJ9BVvkZwFJ0B95o57K0/XA=
@@ -368,8 +370,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/alertmanager v0.28.0 h1:sLN+6HhZet8hrbmGHLAHWsTXgZSVCvq9Ix3U3wvivqc=
github.com/prometheus/alertmanager v0.28.0/go.mod h1:/okSnb2LlodbMlRoOWQEKtqI/coOo2NKZDm2Hu9QHLQ=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
@@ -611,10 +611,10 @@ gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 h1:mepRgnBZa07I4TRuomDE4sTIYieg/osKmzIf4USdWS4=
google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 h1:M1rk8KBnUsBDg1oPGHNCxG4vc1f49epmTO7xscSajMk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba h1:B14OtaXuMaCQsl2deSvNkyPKIzq3BjfxQp8d00QyWx4=
google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba/go.mod h1:G5IanEx8/PgI9w6CFcYQf7jMtHQhZruvfM1i3qOqk5U=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba h1:UKgtfRM7Yh93Sya0Fo8ZzhDP4qBckrrxEr2oF5UIVb8=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM=
google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig=

View File

@@ -3,7 +3,7 @@ module github.com/grafana/grafana/apps/preferences
go 1.25.5
require (
github.com/grafana/grafana-app-sdk v0.48.4
github.com/grafana/grafana-app-sdk v0.48.5
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250804150913-990f1c69ecc2
k8s.io/apimachinery v0.34.2
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912

Some files were not shown because too many files have changed in this diff Show More