Skip to content

Version Packages#176

Merged
sandornagy517 merged 1 commit into
nextfrom
changeset-release/next
Jul 2, 2026
Merged

Version Packages#176
sandornagy517 merged 1 commit into
nextfrom
changeset-release/next

Conversation

@github-actions

@github-actions github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and publish to npm yourself or setup this action to publish automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to next, this PR will be updated.

Releases

@pagerduty/backstage-plugin@0.21.0

Minor Changes

  • bee64f1: Release the service mappings feature

Patch Changes

  • Updated dependencies [bee64f1]
    • @pagerduty/backstage-plugin-common@0.5.0

@pagerduty/backstage-plugin-backend@0.14.0

Minor Changes

  • bee64f1: Release the service mappings feature

Patch Changes

  • Updated dependencies [bee64f1]
    • @pagerduty/backstage-plugin-common@0.5.0

@pagerduty/backstage-plugin-common@0.5.0

Minor Changes

  • bee64f1: Release the service mappings feature

@pagerduty/backstage-plugin-entity-processor@0.4.0

Minor Changes

  • bee64f1: Release the service mappings feature

Patch Changes

  • Updated dependencies [bee64f1]
    • @pagerduty/backstage-plugin-common@0.5.0

@pagerduty/backstage-plugin-scaffolder-actions@0.3.1

Patch Changes

  • Updated dependencies [bee64f1]
    • @pagerduty/backstage-plugin-common@0.5.0

@github-actions github-actions Bot requested a review from a team as a code owner July 2, 2026 14:39
@sandornagy517 sandornagy517 merged commit c5ad550 into next Jul 2, 2026
18 checks passed
@sandornagy517 sandornagy517 deleted the changeset-release/next branch July 2, 2026 14:51
sandornagy517 added a commit that referenced this pull request Jul 3, 2026
* Release custom fields mapping (#169)

* feat: add migration for pagerduty_custom_fields table (#140)

* feat: add CustomFieldsTab component to PagerDutyPage (#141)

* feat: add CustomFieldsTab component to PagerDutyPage

* refactor: remove unused MAX_MAPPINGS constant and related logic from CustomFieldsTab

* feat: implement custom fields management for PagerDuty integration (#145)

* feat: implement custom fields management for PagerDuty integration

* feat: enhance error handling for custom fields in PagerDuty integration

* feat: remove unused custom field retrieval methods and limit checks in CustomFieldsController

* feat: update error handling for custom field creation and limit checks in CustomFieldsController and CustomFieldsTab

* feat: add tests for custom fields creation and retrieval endpoints

* fix: remove type duplication

* fix import and mock api

* fix unit tests

* remove type duplication

* fix unit tests

* fix unit tests and error messages

* implement insertCustomField method with error handling and retrieval

* feat: enhance custom field methods to support account filtering and improve error handling

* feat: add AddCustomFieldModal component and integrate it into CustomFieldsTab; update getCustomFields test

* feat: update createCustomField method to return structured result; enhance error handling and update related tests

* DEVECO-533: Edit custom fields (#148)

* feat: add updateCustomField functionality to PagerDuty integration

- Implemented updateCustomField method in the PagerDuty API to allow updating existing custom fields.
- Enhanced error handling for name and entity path conflicts during updates.
- Added corresponding tests for updateCustomField functionality in both frontend and backend.
- Updated AddCustomFieldModal to support editing existing custom fields.
- Integrated update functionality into CustomFieldsTab with a new action menu for editing custom fields.

* feat: refactor custom fields controller and add helper functions

- Introduced customFieldsHelpers module to encapsulate validation and error handling logic.
- Refactored createCustomField and updateCustomField methods to utilize new helper functions for input validation and error management.
- Enhanced error handling for entity path uniqueness and improved response messages.
- Normalized description handling for custom fields during creation and updates.

* feat: update CustomFieldsTab UI and functionality

- Replaced Link component with a Button for adding new custom fields, enhancing user interaction.
- Updated the section subtitle to better reflect the purpose of the tab.
- Added a new Description column in the custom fields table for improved data visibility.
- Adjusted the empty state message to accommodate the new column layout.
- Swapped MoreVertIcon for MoreHorizIcon in the action menu for consistency.

* feat: enhance error handling in PagerDutyClient for custom fields

* feat: add CustomFieldModal component for managing custom fields

- Replaced AddCustomFieldModal references in CustomFieldsTab with the new CustomFieldModal.

* refactor: remove unused disabled menu items from CustomFieldsTab

- Removed "Disable" and "Delete" menu items from the action menu in CustomFieldsTab to streamline the UI and eliminate unnecessary options.

* fix: prevent race conditions in CustomFieldsTab update logic

- Captured field ID early in the update process to avoid potential race conditions when updating custom fields.
- Updated references to use the captured field ID instead of directly accessing the menuField ID.

* fix: improve error handling in handlePagerDutyError function

- Updated error handling logic to provide more specific messages for different HTTP error statuses (400, 401, 403, 404, 409, 429).
- Enhanced clarity of error messages related to custom field limits and authentication issues in PagerDuty integration.

* refactor: update CustomFieldModal and CustomFieldsTab components

- Refactored CustomFieldModal to use new dialog components from @backstage/ui, improving UI consistency.

* feat: add unique indexes for custom fields in migrations

- Introduced a new migration to add unique indexes on the `pagerduty_custom_fields` table for `backstageEntityMappingPath` and `pagerdutySubdomain`, as well as `pagerdutyCustomFieldDisplayName` and `pagerdutySubdomain`.
- Removed the `findCustomFieldByEntityPath` method from the `PagerDutyBackendStore` interface and its implementation to streamline the codebase.
- Updated the `CustomFieldsController` to handle database errors more effectively during custom field creation and updates, improving overall error management.

* refactor: consolidate error handling and validation in CustomFieldsController

- Removed the customFieldsHelpers module and integrated its functionality directly into the CustomFieldsController.
- Updated methods to use class methods for validation and error handling, improving code organization and readability.
- Enhanced error management for database and PagerDuty interactions, providing clearer responses for various error scenarios.
- Added private methods for input validation, sanitization, and description normalization to streamline custom field processing.

* fix: prevent unnecessary form resets in CustomFieldModal

* refactor: improve state management and modal handling in CustomFieldsTab

- Renamed state variable for clarity from `menuField` to `selectedCustomField`.
- Consolidated modal handling logic into a single function to streamline opening and closing of modals.
- Updated the CustomFieldModal to handle both editing and adding custom fields more efficiently.
- Enhanced error handling and state management during custom field updates.

* feat: implement uniqueness validation for custom fields in CustomFieldsController

- Added a new method to validate uniqueness constraints for display names and entity paths before updating PagerDuty, preventing synchronization issues.
- Enhanced error handling to return appropriate conflict messages when duplicates are detected.
- Introduced tests to ensure validation logic works correctly and prevents invalid updates.

* feat: enhance custom field management with delete and update functionality

- Added methods to delete custom fields and update their PagerDuty IDs in the PagerDutyBackendDatabase.
- Updated CustomFieldsController to handle the creation and updating of custom fields with rollback mechanisms for error handling.
- Implemented tests to ensure proper rollback behavior when PagerDuty operations fail, maintaining data consistency between Backstage and PagerDuty.

* fix: Rebase after service mappings release

* fix: Remove inline styles

* feat: Push custom fields to PagerDuty during catalog processing (#162)

* feat: Push custom fields to PD during catalog processing

* refactor: Extract custom fields push into dedicated processor

Split custom field value sync out of PagerDutyEntityProcessor into a
new PagerDutyCustomFieldsProcessor, return the PagerDuty response body
from the sync endpoint, and consolidate DB row mapping via a helper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat: sync logs tab + record sync failures/skips (#168)

* feat: add sync logs tab to display custom field sync history

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: record custom field sync failures and skips in sync logs

Catalog processor now writes a sync log entry whenever a custom field
push to PagerDuty fails or a field is skipped because its entity path
does not resolve. Writes are fire-and-forget so they don't slow down
catalog processing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: group custom fields components and extract shared error mapper

Move CustomFields-related components into a dedicated subfolder and
share the toFieldErrors helper through a new customFieldErrors util to
remove the duplicated implementation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: add smoke tests and polish sync logs tab

Add frontend smoke tests for ButtonTabs, CustomFieldsTabPanel,
SyncLogsFilters, SyncLogsTab, and the CustomFields wrapper. Switch
SyncLogsTab to receive filters through useTable's filter prop so
pagination resets on filter changes, display full date+time in the
Timestamp column, and widen that column so values fit on one line.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: classify INVALID_PATH sync logs as warning instead of error

Path-resolution failures are expected when entities lack an optional
field, so they shouldn't be surfaced as errors in the sync logs tab.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat: add visual empty state for custom fields and sync logs tables

Replaces plain text empty states with a centered layout. The custom
fields empty state shows two disabled input placeholders with an arrow
icon to hint at the mapping concept; the sync logs empty state is
centered using a Flex wrapper. Styles use makeStyles throughout.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: remove unused AutoMatchEntityMappingsResponse import

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat: enable/disable custom fields (#170)

Add a toggle to enable or disable a custom field from the Custom Fields
tab. Disabled fields are filtered out of the enabled view and do not
count against PagerDuty's custom field hard limit.

Backend:
- Add setCustomFieldEnabled to the DB store
- Add PATCH /custom-fields/:id/enabled route + controller using the
  DB-first -> PagerDuty -> rollback-on-failure pattern
- Add BackstageCustomFieldToggleEnabledRequest to common types
- Add router tests covering disable, validation, 404, and rollback

Frontend:
- Add setCustomFieldEnabled to PagerDutyApi/PagerDutyClient + mock
- Add Enable/Disable menu action with error snackbar and disabled-row
  styling in CustomFieldsTabPanel

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat: start/stop custom field data sync (DEVECO-537) (#171)

* feat: start/stop custom field data sync (DEVECO-537)

Wire up the org-wide data sync toggle so customers must opt in before any
custom field values are pushed to PagerDuty during catalog processing.

- Persist the toggle in the settings table under settings::data-sync
  (value enabled/disabled), validated separately by id in the router so the
  dependency-strategy setting is untouched.
- Gate PagerDutyCustomFieldsProcessor on isDataSyncEnabled(); default to
  disabled when the setting was never saved (opt-in).
- Wire the frontend Switch to React Query (useQuery read + useMutation write
  with optimistic update/rollback); unsaved is treated as disabled with no
  write on load.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: prevent SSRF via origin allow-list and path segment encoding

Add an allow-list origin guard in fetchWithRetries that validates every
outgoing request URL against configured PagerDuty API origins, rejecting
any URL whose host isn't in the server-controlled set. Also encodeURIComponent
each user-controlled path segment (serviceId, fieldId) and rebuild the
getSerivcesByIdsAndAccount query string with URLSearchParams to eliminate
raw interpolation sinks, satisfying CodeQL js/request-forgery (alert #8).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat: delete custom field (DEVECO-534) (#172)

Implements the delete custom field feature end-to-end: DELETE endpoint
on the backend, PagerDuty API call to remove the global custom field,
and a self-contained DeleteCustomFieldDialog component in the frontend
that owns its own state and logic.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: automated cleanup for custom field sync logs (#173)

* feat: automated cleanup for custom field sync logs

Adds a scheduled background task that keeps the sync logs table
bounded: rows older than 30 days are deleted and a global hard cap
of 500k rows trims the oldest entries beyond it. Deletes run in 10k
batches via id-subquery (portable across SQLite and Postgres) so
concurrent sync inserts are never blocked, and the task runs with a
global scheduler lock so only one replica executes it. All thresholds
are configurable under pagerDuty.customFieldsSyncLogs.

Also adds a Refresh button next to Export CSV on the Sync Logs tab,
a bare timestamp index needed by the TTL deletes, and fixes two
pre-existing lint errors (duplicate describe title, explicit any).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: address PR review feedback for sync logs cleanup

- Fix getSyncLogs total returning NaN (count property access lost when
  removing `as any`); type the count query via a generic instead.
- Extract repeated batch sleep delay into BATCH_SLEEP_MS constant.
- Make the batch-budget-exhausted warning name the config knobs to tune.
- Extract SYNC_LOGS_CLEANUP_TASK_ID / timeout / initial-delay constants
  and share the task id between plugin.ts and plugin.test.ts.
- Add coverage for the age-empties-table / cap-no-op path.
- Fix stale olderThanMinutes -> olderThanDays in DB test options.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

* refactor: adjust for Backstage 1.51.2 and port PagerDutyPage to @backstage/ui (#174)

* refactor: adjust for Backstage 1.51.2 upgrade

Bump Backstage version 1.47.3 -> 1.51.2 and adapt to breaking changes:
- Move catalogProcessingExtensionPoint import out of /alpha
- Drop removed variant="gridItem" prop from Entity* cards
- Switch @backstage/ui to managed backstage:^ version
- Add explicit blueprint defineParams type annotations in dev
- Consolidate PagerDuty nav item into PageBlueprint title/icon params

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor: restructure PagerDuty page into Configuration and ServiceMapping pages

Split the monolithic PagerDutyPage into three SubPageBlueprint extensions
(Service Mapping, Custom Fields, Configuration) so each tab is lazily loaded
and independently navigable via the Backstage frontend plugin system.

Also switches `tableProps.loading` to `tableProps.isPending` in MappingsTableContent
and SyncLogsTab to align with the @backstage/ui@0.15.0 API (loading is deprecated).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: bump ui-refactors prerelease versions to .8

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: reposition alerts and tidy styles on PagerDuty pages

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: Fix edited package jsons

* refactor: add PagerDuty service caching and batch insert chunking

Wire a 20-minute CacheService layer into getAllServices and getServiceById
so repeated calls within a request (auto-match, confirm, bulk mapping) hit
the cache rather than the PagerDuty API. Also batches getSerivcesByIdsAndAccount
into 50-id chunks to stay within API gateway URL-length limits, and chunks
bulkInsertEntityMappings into 200-row transactions to avoid SQLite's 500-term
compound SELECT limit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: surface freshly-created mappings before processor writes annotations back

The entity list read path computed status only when a PagerDuty service could
be resolved from the entity's catalog annotations. A just-created mapping has a
DB row but no annotation yet (the entity processor writes it back on the next
catalog processing cycle), so the entity showed NotMapped despite a matching
mapping row.

When a stored mapping is matched by entityRef but the service can't be resolved
from the (still-empty) annotations, fall back to the mapping's serviceId so the
mapping appears immediately as OutOfSync and progresses to InSync once the
annotation lands. Resolution reuses the already-fetched current-page services,
so no extra API or DB calls are made.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: drop malformed service ids before batch PagerDuty lookup

The entity-mapping page returned 400 "Failed to get service. Caller
provided invalid arguments." whenever the status filter was set. Status
is computed at request time, so that filter is the only path that calls
getServicesByIds, which packed every collected service id into a single
GET /services?id[]=... request. PagerDuty rejects the whole batch with a
400 if any one id is malformed (a pasted service URL, trailing
whitespace, a typo), so one bad annotation failed the entire page.

- Add isValidServiceId and sanitize ids in getSerivcesByIdsAndAccount
  before batching (removes the 400 trigger).
- Make getServicesByIdsBatch treat a list-endpoint 400 as no matches
  rather than throwing; single-service lookups still throw on 400.
- Fix getServicesByIds to accumulate results across accounts instead of
  overwriting (multi-account bug).
- Thread a logger into the mappings controller and warn about malformed
  annotation ids so operators know which entity to fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: evict service cache after integration creation to prevent duplicates

Pass the cache through to createServiceIntegration and delete the per-service
and all-services cache entries immediately after a new integration is created,
so the next read re-fetches fresh data instead of returning a stale integrations
array that could cause duplicate Backstage integrations within the cache TTL.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: restore Custom Fields and Configuration tabs on legacy PagerDutyPage

The @backstage/ui port reduced the legacy PagerDutyPage routable extension
to rendering only ServiceMappingPage, silently dropping the Custom Fields
and Configuration tabs for any consumer still on the old Frontend System.
Restore all three tabs via TabbedLayout at their original paths
(/service-mapping, /custom-fields, /settings), reusing the new @backstage/ui
page components so the legacy path stays consistent with the alpha
SubPageBlueprint path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat: link mapping table entity names to their catalog page

The Name column on the service-mapping page rendered the entity name as
plain text. Add a NameCell that links to the entity's catalog page,
mirroring ServiceCell's underlined link styling.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat: client-side nav for mapping names; handle 404 on custom-field delete

NameCell now renders the entity name via core-components' router-aware Link
(to=) instead of CellText's href, which emitted a plain <a> and forced a full
page reload when navigating to the catalog entity.

customFieldsController treats a 404 from PagerDuty on delete as already-deleted
and proceeds to remove the Backstage record so the two sides don't drift, with
tests covering the success, missing-record, PD-404, and PD-500 paths.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: clarify mapping toast wording about async catalog re-processing

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat: add "info" sync-log type for successful custom-field syncs

Records a per-field SYNC_SUCCESS log when the entity processor pushes
custom field values to PagerDuty, giving operators positive sync signal
instead of only failures.

Severity is computed from errorCode (not stored), so the binary
error/warning derivation is reworked to three-way: warning now excludes
both error and info codes in the backend query and the frontend badge.
Adds a blue "Info" badge and a matching option in the Severity filter.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: address PR review findings on service caching and config save

Resolves four findings from the PR #174 review:

- getServicesByIdsBatch: set `limit` to the batch size on the `id[]`
  query so a full 50-id batch isn't truncated to PagerDuty's default
  25-item page (services 26+ were silently dropped, leaving entities
  NotMapped).
- getAllServices: treat an empty cached list as a valid hit
  (`cached != null`) so zero-service accounts use the cache instead of
  re-fetching the full paginated list on every call.
- router POST /services/:serviceId/integration/:vendorId: pass `cache`
  to createServiceIntegration so the per-service and all-services cache
  entries are evicted after a standalone integration is created,
  preventing a stale read within the TTL from creating a duplicate.
- ConfigurationPage: await storeSettings and, on failure, roll back the
  optimistic radio selection and surface an error alert instead of
  silently dropping the rejected promise.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: Generate changese

* fix: Linter issues

---------

Co-authored-by: Renan Oliveira <97949554+renannoliveira@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Version Packages (#176)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: Renan Oliveira <97949554+renannoliveira@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant