Skip to content

feat(bulk-import): add support for on-hehalf-of user access#2647

Merged
PatAKnight merged 11 commits intoredhat-developer:mainfrom
PatAKnight:on-behalf-of
Apr 8, 2026
Merged

feat(bulk-import): add support for on-hehalf-of user access#2647
PatAKnight merged 11 commits intoredhat-developer:mainfrom
PatAKnight:on-behalf-of

Conversation

@PatAKnight
Copy link
Copy Markdown
Member

@PatAKnight PatAKnight commented Mar 30, 2026

Hey, I just made a Pull Request!

Bulk Import now loads repository and organization listings on behalf of the signed-in user. Listing calls use the user’s OAuth token for each configured source code management (SCM) host (GitHub and GitLab), so results match that user’s access instead of the server-wide integration identity (GitHub App, PAT, or GitLab token).

Listing is a hard requirement on user OAuth: GET /repositories and GET /organizations/{org}/repositories require a valid X-SCM-Tokens header (see below). There is no fallback to integration credentials for those endpoints—requests without a usable token map are rejected with HTTP 401. Deployments that previously relied on integration-only listing must configure SCM auth providers and register ScmAuthApi (see plugin READMEs).

How it works

  1. Discover SCM hosts — The frontend calls GET /api/bulk-import/scm-hosts, which returns the configured GitHub and GitLab integration base URLs.

  2. Collect user tokens — For each host, the frontend uses Backstage’s ScmAuthApi (@backstage/integration-react) to request the signed-in user’s OAuth token for that host (read-oriented scope).

  3. Forward tokens to the backend — Tokens are sent as a JSON map keyed by integration base URL (e.g. { "https://github.com": "…" }) in the X-SCM-Tokens request header on listing calls. The header is required for the repository listing endpoints; invalid JSON, an empty map, or an oversized header results in 401.

  4. Backend calls GitHub/GitLab as the user — The backend resolves the token per host and uses it when calling the GitHub or GitLab API so listings are scoped to the user.

  5. Security / audit — The X-SCM-Tokens header is removed from the request before permission checks and audit event creation so token values are not written to audit logs.

Which issue(s) does this PR fix

✔️ Checklist

  • A changeset describing the change and affected packages. (more info)
  • Added or Updated documentation
  • Tests for new functionality and regression tests for bug fixes
  • Screenshots attached (for UI changes)

Documentation

  • Frontend: plugins/bulk-import/README.md (including auth provider setup).
  • Backend: plugins/bulk-import-backend/README.md and generated API docs under plugins/bulk-import-backend/api-docs/.
  • OpenAPI: plugins/bulk-import-backend/src/schema/openapi.yaml.

How to test

  • /scm-hosts — Call GET /api/bulk-import/scm-hosts (curl or Swagger). Confirm configured GitHub and, if applicable, GitLab hosts appear in the response.

  • Happy path (GitHub or GitLab) — Configure the matching SCM OAuth provider and sign in. Open Bulk Import → repository selection. Confirm the list reflects repos the user can access (including cases where that differs from what the server integration alone could see).

  • GitLab parity — With GitLab integration + GitLab auth configured, repeat listing flows and confirm GitLab responses use the user token the same way as GitHub.

  • Hard requirement — Omit X-SCM-Tokens or send an empty object on a listing request (e.g. direct API call); expect 401. With the UI, misconfigured or missing ScmAuthApi / OAuth should surface a clear error instead of silently using integration credentials for listing.

  • Cross-user isolation (optional) — Sign in as two users with different SCM access; each listing should only include repositories that user is authorized to see.

@rhdh-qodo-merge
Copy link
Copy Markdown

Review Summary by Qodo

Implement "On Behalf of User Access" for Bulk Import plugin with OAuth token forwarding

✨ Enhancement 🧪 Tests 📝 Documentation

Grey Divider

Walkthroughs

Description
• Implements "On Behalf of User Access" feature enabling the Bulk Import plugin to fetch repository
  and organization listings using signed-in user's OAuth tokens instead of server-wide credentials
• **Backend changes:**
  - New /api/bulk-import/scm-hosts endpoint to discover configured GitHub and GitLab integration
  hosts
  - Added x-scm-tokens header support for forwarding user OAuth tokens to backend API calls
  - Implemented parseScmTokensHeader and extractUserTokens functions with 4KB size limit
  validation
  - Created unified GitApiService interface for consistent GitHub and GitLab provider abstraction
  - Updated GitHub and GitLab services to accept optional userTokens parameter and create
  user-scoped API instances without cache to prevent cross-user data leakage
  - Refactored repository, organization, and import handlers to use GitApiService interface
  - Extracted shared SCM types to unified module for code reuse
• **Frontend changes:**
  - Implemented useAsync hook in useRepositories to fetch SCM hosts and collect user OAuth tokens
  via ScmAuthApi
  - Updated API client to include X-SCM-Tokens header when user tokens are available
  - Added getSCMHosts() method to BulkImportAPI type
  - Refactored path providers to extend BulkImportRESTPathProviderBase with proper URL encoding
  using URLSearchParams
• **Graceful fallback:** When OAuth tokens are unavailable or providers not configured, backend
  silently falls back to server-side credentials with no errors
• **Comprehensive test coverage:** Added tests for SCM host discovery, token collection, header
  validation, and user token paths in both GitHub and GitLab services
• **Full documentation:** Updated README files, OpenAPI schemas, and API documentation for both
  backend and frontend
Diagram
flowchart LR
  User["User Signs In"]
  Frontend["Frontend Plugin"]
  ScmAuth["ScmAuthApi"]
  Backend["Backend Router"]
  GithubSvc["GitHub Service"]
  GitlabSvc["GitLab Service"]
  GithubAPI["GitHub API"]
  GitlabAPI["GitLab API"]
  
  User -->|Authenticates| Frontend
  Frontend -->|Discovers Hosts| Backend
  Backend -->|Returns SCM Hosts| Frontend
  Frontend -->|Collects Tokens| ScmAuth
  ScmAuth -->|User OAuth Tokens| Frontend
  Frontend -->|Forwards Tokens<br/>x-scm-tokens Header| Backend
  Backend -->|Routes to Services| GithubSvc
  Backend -->|Routes to Services| GitlabSvc
  GithubSvc -->|User-Scoped Request| GithubAPI
  GitlabSvc -->|User-Scoped Request| GitlabAPI
  GithubAPI -->|User Repositories| GithubSvc
  GitlabAPI -->|User Repositories| GitlabSvc
  GithubSvc -->|Results| Backend
  GitlabSvc -->|Results| Backend
  Backend -->|Filtered Results| Frontend
Loading

Grey Divider

File Changes

1. workspaces/bulk-import/plugins/bulk-import-backend/src/generated/openapi.d.ts ✨ Enhancement +89/-4

OpenAPI type definitions for SCM hosts and token headers

• Added xSCMTokensHeaderParam to header parameters for SCM token map support
• Introduced SCMTokenMap and SCMHostList schema types with detailed documentation
• Updated FindAllRepositories and FindRepositoriesByOrganization paths to include header
 parameters for x-scm-tokens
• Added new FindAllSCMHosts path with 200 response returning SCMHostList
• Exported new types SCMHostList and SCMTokenMap for public API

workspaces/bulk-import/plugins/bulk-import-backend/src/generated/openapi.d.ts


2. workspaces/bulk-import/plugins/bulk-import-backend/src/service/router.ts ✨ Enhancement +89/-9

Backend router support for user token forwarding

• Added findAllSCMHosts handler import and operation constant
• Implemented parseScmTokensHeader and extractUserTokens functions to validate and parse
 x-scm-tokens header with 4KB size limit
• Registered new /scm-hosts endpoint handler that returns configured GitHub and GitLab integration
 hosts
• Updated findAllRepositories and findRepositoriesByOrganization handlers to extract and pass
 userTokens to API services
• Fixed permission check error handling to properly propagate exceptions
• Added audit event for scm-read operation

workspaces/bulk-import/plugins/bulk-import-backend/src/service/router.ts


3. workspaces/bulk-import/plugins/bulk-import-backend/src/github/githubApiService.ts ✨ Enhancement +99/-6

GitHub service user token support implementation

• Implemented GitApiService interface in GithubApiService class
• Added fetchUserTokenGithubIntegrationRepositories method to handle user-scoped OAuth token
 requests
• Updated getRepositoriesFromIntegrations and getOrgRepositoriesFromIntegrations to accept
 optional userTokens parameter
• When user tokens are provided, creates user-scoped Octokit instances without cache to prevent
 cross-user data leakage
• Added return type annotations to async methods for better type safety

workspaces/bulk-import/plugins/bulk-import-backend/src/github/githubApiService.ts


View more (38)
4. workspaces/bulk-import/plugins/bulk-import/src/hooks/useRepositories.test.ts 🧪 Tests +175/-0

Tests for SCM auth token collection in repositories hook

• Added mock for useApiHolder to support ScmAuthApi testing
• Added test suite for SCM auth token collection covering successful token fetching, error handling,
 and graceful fallback scenarios
• Tests verify that tokens are collected from scmAuth.getCredentials and that missing providers
 are handled gracefully
• Tests confirm that getSCMHosts failures prevent token fetching attempts

workspaces/bulk-import/plugins/bulk-import/src/hooks/useRepositories.test.ts


5. workspaces/bulk-import/plugins/bulk-import-backend/src/gitlab/gitlabApiService.ts ✨ Enhancement +78/-3

GitLab service user token support implementation

• Implemented GitApiService interface in GitlabApiService class
• Added fetchUserTokenGitlabIntegrationRepositories method to handle user-scoped OAuth token
 requests
• Updated getRepositoriesFromIntegrations and getOrgRepositoriesFromIntegrations to accept
 optional userTokens parameter
• When user tokens are provided, creates user-scoped Gitlab instances and uses them for API calls
• Fixed comment to reference GitLab instead of GitHub

workspaces/bulk-import/plugins/bulk-import-backend/src/gitlab/gitlabApiService.ts


6. workspaces/bulk-import/plugins/bulk-import/src/hooks/useRepositories.ts ✨ Enhancement +67/-39

Frontend hook for user OAuth token collection and forwarding

• Added useApiHolder and scmAuthApiRef imports for OAuth token collection
• Implemented useAsync hook to fetch SCM hosts and collect user OAuth tokens from
 scmAuth.getCredentials
• Tokens are collected per-host with read-only scope and gracefully skip hosts without OAuth
 providers
• Updated fetchRepositories to pass scmAuthTokens to backend via API options
• Added token generation memoization to include tokens in query cache key
• Updated query hook to wait for token loading before executing repository fetch

workspaces/bulk-import/plugins/bulk-import/src/hooks/useRepositories.ts


7. workspaces/bulk-import/plugins/bulk-import-backend/src/generated/openapidocument.ts 📝 Documentation +88/-1

OpenAPI document updates for SCM hosts endpoint

• Added /scm-hosts GET endpoint definition with findAllSCMHosts operation
• Added xSCMTokensHeaderParam parameter definition to /repositories and
 /organizations/{organizationName}/repositories endpoints
• Added SCMTokenMap and SCMHostList schema definitions with detailed descriptions and examples
• Added scmHosts example showing GitHub and GitLab host URLs

workspaces/bulk-import/plugins/bulk-import-backend/src/generated/openapidocument.ts


8. workspaces/bulk-import/plugins/bulk-import/src/api/BulkImportBackendClient.test.ts 🧪 Tests +86/-1

Tests for SCM hosts API and token header forwarding

• Added mock handler for GET /api/bulk-import/scm-hosts endpoint returning GitHub and GitLab hosts
• Added test suite for getSCMHosts method covering successful retrieval and error response
 handling
• Added test suite for dataFetcher X-SCM-Tokens header validation covering presence, absence, and
 empty token scenarios
• Fixed organization repository URL encoding in mock handler

workspaces/bulk-import/plugins/bulk-import/src/api/BulkImportBackendClient.test.ts


9. workspaces/bulk-import/plugins/bulk-import-backend/src/service/handlers/scm/scm.test.ts 🧪 Tests +140/-0

Tests for SCM hosts discovery handler

• New test file for findAllSCMHosts handler
• Tests verify correct extraction of GitHub and GitLab host URLs from configuration
• Tests confirm GitLab baseUrl trailing slash normalization
• Tests validate handling of single or missing integration types
• Tests verify multiple integrations are returned in order

workspaces/bulk-import/plugins/bulk-import-backend/src/service/handlers/scm/scm.test.ts


10. workspaces/bulk-import/plugins/bulk-import-backend/src/gitlab/gitlabApiService.test.ts 🧪 Tests +118/-0

Tests for GitLab user token support

• Added test suite for user token path in getRepositoriesFromIntegrations and
 getOrgRepositoriesFromIntegrations
• Tests verify user token path is used when matching host token is provided
• Tests confirm empty repositories returned when no host matches provided tokens
• Tests validate fallback to server credentials when userTokens is undefined or empty object

workspaces/bulk-import/plugins/bulk-import-backend/src/gitlab/gitlabApiService.test.ts


11. workspaces/bulk-import/plugins/bulk-import/src/api/BulkImportBackendClient.ts ✨ Enhancement +31/-21

Frontend API client for SCM hosts and token headers

• Added getSCMHosts() method to BulkImportAPI type returning GitHub and GitLab host arrays or
 Response
• Updated dataFetcher to include X-SCM-Tokens header when scmAuthTokens are provided in
 options
• Moved IBulkImportRESTPathProvider interface to new base class file and exported it
• Added getSCMHosts implementation calling /api/bulk-import/scm-hosts endpoint

workspaces/bulk-import/plugins/bulk-import/src/api/BulkImportBackendClient.ts


12. workspaces/bulk-import/plugins/bulk-import-backend/src/scm/GitApiService.ts ✨ Enhancement +132/-0

Unified GitApiService interface for SCM providers

• New file defining GitApiService interface as unified contract for GitHub and GitLab
 implementations
• Interface includes methods for repository/organization fetching, PR management, and file
 operations
• All repository methods accept optional userTokens parameter for user-scoped access
• Provides consistent abstraction across different SCM providers

workspaces/bulk-import/plugins/bulk-import-backend/src/scm/GitApiService.ts


13. workspaces/bulk-import/plugins/bulk-import-backend/src/github/githubApiService.test.ts 🧪 Tests +105/-0

Tests for GitHub user token support

• Added test suite for user token path in getRepositoriesFromIntegrations and
 getOrgRepositoriesFromIntegrations
• Tests verify user token path is used when matching host token is provided
• Tests confirm empty repositories returned when no host matches provided tokens
• Tests validate fallback to server credentials when userTokens is undefined or empty object

workspaces/bulk-import/plugins/bulk-import-backend/src/github/githubApiService.test.ts


14. workspaces/bulk-import/plugins/bulk-import-backend/src/service/handlers/repository/repositories.ts ✨ Enhancement +17/-12

Repository handlers refactored for unified SCM interface

• Updated function signatures to use GitApiService interface instead of concrete GitHub/GitLab
 types
• Replaced approvalTool parameter with userTokens in findAllRepositories
• Added userTokens parameter to findRepositoriesByOrganization
• Updated type imports to use shared SCM types from scm/types module

workspaces/bulk-import/plugins/bulk-import-backend/src/service/handlers/repository/repositories.ts


15. workspaces/bulk-import/plugins/bulk-import/src/api/OrchestratorBulkImportBackendClientPathProvider.ts ✨ Enhancement +18/-7

Orchestrator path provider refactored for base class

• Changed to extend BulkImportRESTPathProviderBase instead of implementing interface
• Updated path building to use URLSearchParams for proper query string encoding
• Made approvalTool parameter optional in path methods

workspaces/bulk-import/plugins/bulk-import/src/api/OrchestratorBulkImportBackendClientPathProvider.ts


16. workspaces/bulk-import/plugins/bulk-import/src/api/PRBulkImportBackendClientPathProvider.ts ✨ Enhancement +18/-7

PR path provider refactored for base class

• Changed to extend BulkImportRESTPathProviderBase instead of implementing interface
• Updated path building to use URLSearchParams for proper query string encoding
• Made approvalTool parameter optional in path methods

workspaces/bulk-import/plugins/bulk-import/src/api/PRBulkImportBackendClientPathProvider.ts


17. workspaces/bulk-import/plugins/bulk-import-backend/src/github/types.ts ✨ Enhancement +7/-75

GitHub types refactored to use shared SCM types

• Replaced local type definitions with re-exports from shared scm/types module
• Maintains backward compatibility by aliasing SCM* types to Github* names
• Reduces code duplication and establishes single source of truth for SCM types

workspaces/bulk-import/plugins/bulk-import-backend/src/github/types.ts


18. workspaces/bulk-import/plugins/bulk-import-backend/src/gitlab/types.ts ✨ Enhancement +7/-64

GitLab types refactored to use shared SCM types

• Replaced local type definitions with re-exports from shared scm/types module
• Maintains backward compatibility by aliasing SCM* types to Gitlab* names
• Reduces code duplication and establishes single source of truth for SCM types

workspaces/bulk-import/plugins/bulk-import-backend/src/gitlab/types.ts


19. workspaces/bulk-import/plugins/bulk-import-backend/src/service/handlers/import/bulkImports.ts ✨ Enhancement +23/-12

Bulk imports handler refactored for unified SCM interface

• Updated createPR function to accept GitApiService interface instead of concrete types
• Refactored parsePullOrMergeRequestInfo to use object parameter destructuring for better clarity
• Updated type imports to use GitApiService interface

workspaces/bulk-import/plugins/bulk-import-backend/src/service/handlers/import/bulkImports.ts


20. workspaces/bulk-import/plugins/bulk-import/src/api/ScaffolderBulkImportBackendClientPathProvider.ts ✨ Enhancement +18/-7

Scaffolder path provider refactored for base class

• Changed to extend BulkImportRESTPathProviderBase instead of implementing interface
• Updated path building to use URLSearchParams for proper query string encoding
• Made approvalTool parameter optional in path methods

workspaces/bulk-import/plugins/bulk-import/src/api/ScaffolderBulkImportBackendClientPathProvider.ts


21. workspaces/bulk-import/plugins/bulk-import-backend/src/service/handlers/organization/organizations.ts ✨ Enhancement +5/-10

Organization handlers refactored for unified SCM interface

• Updated function signatures to use GitApiService interface instead of concrete GitHub/GitLab
 types
• Reordered parameters in getOrganizationsFromIntegrations call for consistency
• Updated type imports to use shared SCM types from scm/types module

workspaces/bulk-import/plugins/bulk-import-backend/src/service/handlers/organization/organizations.ts


22. workspaces/bulk-import/plugins/bulk-import-backend/src/scm/types.ts ✨ Enhancement +91/-0

Shared SCM types module for provider abstraction

• New file defining shared SCM types used across GitHub and GitLab implementations
• Defines SCMFetchError, SCMOrganization, SCMRepository, and response wrapper types
• Provides unified type contract for all SCM provider implementations

workspaces/bulk-import/plugins/bulk-import-backend/src/scm/types.ts


23. workspaces/bulk-import/plugins/bulk-import-backend/src/github/utils/ghUtils.ts ✨ Enhancement +5/-5

GitHub utilities support optional cache for user tokens

• Updated buildOcto function to accept optional CacheService parameter
• Updated registerHooks to handle undefined cache with optional chaining
• Allows creating Octokit instances without cache for user token requests to prevent cross-user data
 leakage

workspaces/bulk-import/plugins/bulk-import-backend/src/github/utils/ghUtils.ts


24. workspaces/bulk-import/plugins/bulk-import/src/api/BulkImportBackendClientBase.ts ✨ Enhancement +64/-0

Base class for REST path provider implementations

• New file extracting IBulkImportRESTPathProvider interface to base class
• Introduced BulkImportRESTPathProviderBase abstract class with default getSCMHostPath
 implementation
• Provides foundation for path provider implementations to extend

workspaces/bulk-import/plugins/bulk-import/src/api/BulkImportBackendClientBase.ts


25. workspaces/bulk-import/plugins/bulk-import-backend/src/service/handlers/scm/scm.ts ✨ Enhancement +37/-0

SCM hosts discovery handler implementation

• New file implementing findAllSCMHosts handler
• Extracts GitHub host URLs from integration configs as https://{host} format
• Extracts GitLab baseUrl and normalizes by removing trailing slashes
• Returns SCMHostList with both provider arrays

workspaces/bulk-import/plugins/bulk-import-backend/src/service/handlers/scm/scm.ts


26. workspaces/bulk-import/plugins/bulk-import-backend/src/service/handlers/import/importStatus.ts ✨ Enhancement +3/-4

Import status handlers refactored for unified SCM interface

• Updated function signatures to use GitApiService interface instead of concrete GitHub/GitLab
 types
• Updated type imports to use GitApiService interface

workspaces/bulk-import/plugins/bulk-import-backend/src/service/handlers/import/importStatus.ts


27. workspaces/bulk-import/plugins/bulk-import/src/types/types.ts ✨ Enhancement +4/-2

Type definitions updated for user token support

• Added scmAuthTokens optional field to APITypes for passing user tokens to backend
• Made page and querySize optional in DataFetcherQueryParams
• Added approvalTool as required field in DataFetcherQueryParams

workspaces/bulk-import/plugins/bulk-import/src/types/types.ts


28. workspaces/bulk-import/plugins/bulk-import-backend/src/service/router.test.ts 🧪 Tests +5/-0

Router tests for SCM hosts endpoint permissions

• Added test case for GET /scm-hosts endpoint permission framework denial

workspaces/bulk-import/plugins/bulk-import-backend/src/service/router.test.ts


29. workspaces/bulk-import/plugins/bulk-import-backend/README.md 📝 Documentation +39/-4

Backend documentation for user token support feature

• Added comprehensive documentation for "On Behalf of User Access" feature
• Documented new /api/bulk-import/scm-hosts endpoint and its purpose
• Explained token collection flow and fallback behavior for missing OAuth providers
• Added security note about Octokit cache disabling for user tokens
• Updated prerequisites to include optional GitLab integration configuration
• Updated audit events documentation to include scm-hosts-read event

workspaces/bulk-import/plugins/bulk-import-backend/README.md


30. workspaces/bulk-import/plugins/bulk-import-backend/src/schema/openapi.yaml 📝 Documentation +67/-0

OpenAPI schema updates for SCM hosts and token headers

• Added /scm-hosts GET endpoint with findAllSCMHosts operation
• Added xSCMTokensHeaderParam parameter reference to /repositories and
 /organizations/{organizationName}/repositories endpoints
• Added SCMTokenMap and SCMHostList schema definitions with descriptions and examples
• Added scmHosts example showing sample GitHub and GitLab host URLs

workspaces/bulk-import/plugins/bulk-import-backend/src/schema/openapi.yaml


31. workspaces/bulk-import/plugins/bulk-import/README.md 📝 Documentation +43/-0

Frontend documentation for user token support feature

• Added section on "On Behalf of User Access" feature with configuration instructions
• Documented how the plugin discovers SCM hosts and collects user OAuth tokens
• Explained fallback behavior when OAuth providers are not configured
• Provided example auth provider configuration for GitHub and GitLab
• Added note about soft dependency on ScmAuthApi from @backstage/integration-react

workspaces/bulk-import/plugins/bulk-import/README.md


32. workspaces/bulk-import/plugins/bulk-import/.changeset/small-games-live.md 📝 Documentation +0/-0

Changeset for on-behalf-of user access feature

• New changeset documenting the "On Behalf of User Access" feature
• Lists backend changes including new endpoint, token header support, and shared interfaces
• Lists frontend changes including SCM host discovery and token collection
• Explains fallback behavior and graceful degradation when OAuth is not configured

workspaces/bulk-import/plugins/bulk-import/.changeset/small-games-live.md


33. workspaces/bulk-import/plugins/bulk-import-backend/api-docs/README.md 📝 Documentation +3/-1

API documentation updates for SCM hosts endpoint

• Added findAllSCMHosts operation to ManagementApi
• Added SCMHostList model to documentation
• Updated API endpoint listing to include new /scm-hosts endpoint

workspaces/bulk-import/plugins/bulk-import-backend/api-docs/README.md


34. workspaces/bulk-import/plugins/bulk-import/src/utils/repository-utils.tsx ✨ Enhancement +11/-3

Repository utilities refactored for proper URL encoding

• Refactored getApi function to use URLSearchParams for query string construction
• Properly encodes organization names using encodeURIComponent
• Improves URL encoding safety and maintainability

workspaces/bulk-import/plugins/bulk-import/src/utils/repository-utils.tsx


35. workspaces/bulk-import/plugins/bulk-import-backend/api-docs/Apis/OrganizationApi.md 📝 Documentation +2/-1

API documentation for organization repositories with token header

• Updated findRepositoriesByOrganization documentation to include x-scm-tokens header parameter

workspaces/bulk-import/plugins/bulk-import-backend/api-docs/Apis/OrganizationApi.md


36. workspaces/bulk-import/plugins/bulk-import/package.json Dependencies +1/-0

Frontend package dependency for SCM auth integration

• Added @backstage/integration-react dependency for ScmAuthApi support

workspaces/bulk-import/plugins/bulk-import/package.json


37. workspaces/bulk-import/plugins/bulk-import-backend/api-docs/Apis/RepositoryApi.md 📝 Documentation +2/-1

API documentation for repositories with token header

• Updated findAllRepositories documentation to include x-scm-tokens header parameter

workspaces/bulk-import/plugins/bulk-import-backend/api-docs/Apis/RepositoryApi.md


38. workspaces/bulk-import/plugins/bulk-import-backend/api-docs/Apis/ManagementApi.md 📝 Documentation +23/-0

API documentation for SCM hosts discovery endpoint

• Added findAllSCMHosts operation documentation with endpoint, parameters, return type, and
 authorization details

workspaces/bulk-import/plugins/bulk-import-backend/api-docs/Apis/ManagementApi.md


39. workspaces/bulk-import/plugins/bulk-import-backend/api-docs/Models/SCMHostList.md 📝 Documentation +10/-0

API model documentation for SCM host list

• New API model documentation for SCMHostList with github and gitlab array properties

workspaces/bulk-import/plugins/bulk-import-backend/api-docs/Models/SCMHostList.md


40. workspaces/bulk-import/plugins/bulk-import-backend/api-docs/.openapi-generator/FILES 📝 Documentation +1/-0

OpenAPI generator files list update

• Added Models/SCMHostList.md to generated files list

workspaces/bulk-import/plugins/bulk-import-backend/api-docs/.openapi-generator/FILES


41. workspaces/bulk-import/.changeset/small-games-live.md Additional files +31/-0

...

workspaces/bulk-import/.changeset/small-games-live.md


Grey Divider

Qodo Logo

@rhdh-qodo-merge
Copy link
Copy Markdown

rhdh-qodo-merge Bot commented Mar 30, 2026

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 📎 Requirement gaps (2)

Grey Divider


Action required

1. Repo list falls back server 📎 Requirement gap ⛨ Security
Description
When no X-SCM-Tokens header is provided (e.g., ScmAuthApi not registered), the frontend omits
user tokens and the backend falls through to server-wide integration credentials for repository
listing. This can return repositories beyond what the currently logged-in user can access, violating
the user-scoped listing requirement.
Code

workspaces/bulk-import/plugins/bulk-import-backend/src/github/githubApiService.ts[R381-405]

+    // When a user token is present, build a user-scoped Octokit per integration
+    // config and call addGithubTokenRepositories with it. This makes
+    // listForAuthenticatedUser return only repos the user personally has access to.
+    // When absent, fall through to the existing server-credential path.
+    if (userTokens && Object.keys(userTokens).length > 0) {
+      const { errors: allErrors, totalCount } =
+        await this.fetchUserTokenGithubIntegrationRepositories(
+          userTokens,
+          (userOctokit, userCredential, dataFetchErrors) =>
+            addGithubTokenRepositories(
+              { logger: this.logger },
+              userOctokit,
+              userCredential,
+              repositories,
+              dataFetchErrors,
+              { search, pageNumber, pageSize },
+            ),
+        );
+      const repoList = Array.from(repositories.values());
+      return { repositories: repoList, errors: allErrors, totalCount };
+    }
+
    const result = await fetchFromAllIntegrations(
      {
        logger: this.logger,
Evidence
PR Compliance ID 1 requires the repo list to be scoped to the current user. The frontend explicitly
returns undefined tokens when scmAuth is unavailable and only sends X-SCM-Tokens when tokens
exist, while the backend GitHub implementation uses server credentials whenever userTokens is
absent/empty (fall-through to fetchFromAllIntegrations).

Bulk Import GitHub repo list is scoped to the current logged-in user (on-behalf-of)
workspaces/bulk-import/plugins/bulk-import/src/hooks/useRepositories.ts[73-99]
workspaces/bulk-import/plugins/bulk-import/src/api/BulkImportBackendClient.ts[118-137]
workspaces/bulk-import/plugins/bulk-import-backend/src/github/githubApiService.ts[373-409]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Repository listing can fall back to server-wide integration credentials when `X-SCM-Tokens` is absent/empty, which can expose repositories outside the current user's access.

## Issue Context
Compliance requires the Bulk Import GitHub repo list to be scoped to the currently logged-in user. Today, user tokens are optional and the backend falls back to server credentials when tokens are unavailable.

## Fix Focus Areas
- workspaces/bulk-import/plugins/bulk-import/src/hooks/useRepositories.ts[73-106]
- workspaces/bulk-import/plugins/bulk-import/src/api/BulkImportBackendClient.ts[118-137]
- workspaces/bulk-import/plugins/bulk-import-backend/src/github/githubApiService.ts[373-409]
- workspaces/bulk-import/plugins/bulk-import-backend/src/service/router.ts[138-176]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. /scm-hosts audit event mismatch 📎 Requirement gap ⚙ Maintainability
Description
Backend documentation says /scm-hosts emits scm-hosts-read, but the router actually emits the
event id scm-read. This makes the documentation inaccurate for the new behavior.
Code

workspaces/bulk-import/plugins/bulk-import-backend/README.md[R304-306]

+- **`scm-hosts-read`**: tracks `GET` requests to the `/scm-hosts` endpoint, which returns the list of configured GitHub and GitLab integration host URLs.
+
+- **`org-read`**: tracks `GET` requests to the `/organizations` endpoint, which returns the list of organizations accessible from all configured SCM Integrations (GitHub and GitLab).
Evidence
PR Compliance ID 2 requires documentation updates describing the new behavior/expectations; the
updated README introduces an audit event name for /scm-hosts that does not match the
implementation in the router, so the documentation is not correct.

Upstream documentation updates are completed for the Bulk Import GitHub user-scoped repo listing change
workspaces/bulk-import/plugins/bulk-import-backend/README.md[303-306]
workspaces/bulk-import/plugins/bulk-import-backend/src/service/router.ts[805-807]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The README documents the `/scm-hosts` audit event id as `scm-hosts-read`, but the implementation emits `scm-read`.

## Issue Context
This PR adds the `/scm-hosts` endpoint and updates documentation; the documentation must accurately reflect emitted audit events.

## Fix Focus Areas
- workspaces/bulk-import/plugins/bulk-import-backend/README.md[303-306]
- workspaces/bulk-import/plugins/bulk-import-backend/src/service/router.ts[805-807]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Tokens logged in audits 🐞 Bug ⛨ Security
Description
Audit events are created with the full Express request object, so the new x-scm-tokens header
(containing user OAuth tokens) can be persisted in audit logs/events. The header is only deleted
from a copied header object, leaving req.headers unchanged when auditing occurs.
Code

workspaces/bulk-import/plugins/bulk-import-backend/src/service/router.ts[R167-176]

+function extractUserTokens(
+  headers:
+    | Paths.FindAllRepositories.HeaderParameters
+    | Paths.FindRepositoriesByOrganization.HeaderParameters,
+  logger: LoggerService,
+): Record<string, string> | undefined {
+  const raw = headers['x-scm-tokens'] as string | undefined;
+  delete headers['x-scm-tokens']; // consumed; strip before any logging path
+  return parseScmTokensHeader(raw, logger);
+}
Evidence
The router builds audit events for requests using the full req object, and auditCreateEvent stores
that request object; therefore any sensitive headers present on req (including x-scm-tokens) are
captured. The attempted stripping only deletes the header from a cloned headers object (not from
req.headers), so it does not prevent audit capture.

workspaces/bulk-import/plugins/bulk-import-backend/src/helpers/auditorUtils.ts[28-39]
workspaces/bulk-import/plugins/bulk-import-backend/src/service/router.ts[770-787]
workspaces/bulk-import/plugins/bulk-import-backend/src/service/router.ts[167-176]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`x-scm-tokens` contains user OAuth access tokens but is currently included in the Express `req` that is passed into `auditCreateEvent`, which can persist credentials in audit logs.

### Issue Context
The current code deletes `x-scm-tokens` only from a copied headers object (not `req.headers`) and does so inside specific handlers, after the router-level audit middleware already created the audit event.

### Fix Focus Areas
- workspaces/bulk-import/plugins/bulk-import-backend/src/service/router.ts[131-176]
- workspaces/bulk-import/plugins/bulk-import-backend/src/service/router.ts[752-787]

### Implementation guidance
- Parse and validate `x-scm-tokens` in an early middleware that runs **before** `permissionCheck` and before the audit middleware.
- After extracting, immediately `delete req.headers['x-scm-tokens']` (and also handle the case where it may be `string[]`).
- Store the parsed token map in a safe per-request location (e.g., `res.locals.scmTokens` or a typed request extension) and use that in the repository/org-repo handlers instead of reading from headers later.
- Ensure audit events never contain the raw token string.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (2)
4. OpenAPI header type mismatch 🐞 Bug ✓ Correctness
Description
The OpenAPI spec defines x-scm-tokens as an object schema (SCMTokenMap), but the implementation
expects a JSON-encoded string header and JSON.parse’s it. With OpenAPIBackend validation enabled,
sending a string header where the spec expects an object can cause validationFail (400) and break
on-behalf-of requests.
Code

workspaces/bulk-import/plugins/bulk-import-backend/src/schema/openapi.yaml[R613-621]

+    xSCMTokensHeaderParam:
+      in: header
+      name: x-scm-tokens
+      description: >
+        Optional JSON-encoded map of SCM host URL to user authentication token.
+        Used to fetch repositories on behalf of the user for each configured SCM host.
+      required: false
+      schema:
+        $ref: '#/components/schemas/SCMTokenMap'
Evidence
OpenAPIBackend is configured with validate: true and returns 400 on validationFail, so
mismatched parameter types are request-breaking. The spec models x-scm-tokens as an object via
$ref: SCMTokenMap, while the router code treats the header as a raw string and runs JSON.parse
on it, indicating the actual wire format is a JSON string rather than an OpenAPI-serialized object
header.

workspaces/bulk-import/plugins/bulk-import-backend/src/service/router.ts[224-242]
workspaces/bulk-import/plugins/bulk-import-backend/src/schema/openapi.yaml[613-621]
workspaces/bulk-import/plugins/bulk-import-backend/src/schema/openapi.yaml[716-731]
workspaces/bulk-import/plugins/bulk-import-backend/src/service/router.ts[138-165]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The OpenAPI schema models `x-scm-tokens` as an `object` (`SCMTokenMap`), but HTTP headers are strings and the server expects a JSON-encoded string and parses it with `JSON.parse`. With OpenAPIBackend request validation enabled, this schema mismatch can cause 400 validation failures when the header is present.

### Issue Context
The backend explicitly parses the header as JSON text; the schema should reflect that wire format.

### Fix Focus Areas
- workspaces/bulk-import/plugins/bulk-import-backend/src/schema/openapi.yaml[613-621]
- workspaces/bulk-import/plugins/bulk-import-backend/src/schema/openapi.yaml[716-731]
- workspaces/bulk-import/plugins/bulk-import-backend/src/generated/openapidocument.ts[1031-1039]
- workspaces/bulk-import/plugins/bulk-import-backend/src/generated/openapi.d.ts[30-41]

### Implementation guidance
- Change `xSCMTokensHeaderParam.schema` to `type: string` (and update description/example to indicate it is JSON).
 - Optionally keep `SCMTokenMap` schema for documentation purposes, but do not reference it as a header parameter schema unless you also implement OpenAPI object header serialization.
- Regenerate `openapidocument.ts` and `openapi.d.ts` so generated types match the actual string header.
- Keep server-side JSON parsing/validation as-is (or move it earlier per the audit fix).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Token in query key 🐞 Bug ⛨ Security
Description
The frontend includes raw OAuth token values in the React Query key, which can surface in React
Query devtools and other debugging/telemetry that logs query keys. This increases the risk of
accidental credential exposure in the browser.
Code

workspaces/bulk-import/plugins/bulk-import/src/hooks/useRepositories.ts[R116-136]

+  const tokenGeneration = useMemo(
+    () =>
+      scmAuthTokens
+        ? Object.entries(scmAuthTokens)
+            .sort(([a], [b]) => a.localeCompare(b))
+            .map(([k, v]) => `${k}=${v}`)
+            .join(',')
+        : '',
+    [scmAuthTokens],
+  );
+
  const {
    data: value,
    error,
    isLoading: isQueryLoading,
  } = useQuery(
-    [options?.showOrganizations ? 'organizations' : 'repositories', options],
+    [
+      options?.showOrganizations ? 'organizations' : 'repositories',
+      options,
+      tokenGeneration,
+    ],
Evidence
useRepositories builds a tokenGeneration string by concatenating host=token pairs and includes
that value in the query key passed to useQuery, meaning the token values become part of React
Query’s internal cache keying and tooling visibility.

workspaces/bulk-import/plugins/bulk-import/src/hooks/useRepositories.ts[116-143]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
OAuth token values are embedded in the React Query key (`tokenGeneration`), which can be exposed via devtools/debugging/logging of query keys.

### Issue Context
The query key only needs to change when the *effective auth context* changes; it should not contain secrets.

### Fix Focus Areas
- workspaces/bulk-import/plugins/bulk-import/src/hooks/useRepositories.ts[116-143]

### Implementation guidance
- Replace `tokenGeneration` with a non-secret discriminator, e.g.:
 - list of host URLs only: `Object.keys(scmAuthTokens ?? {}).sort().join(',')`
 - or a stable boolean/enum: `hasScmAuthTokens` plus `approvalTool`
 - or a one-way hash that does not include raw tokens (if you truly need to detect token changes)
- Ensure the query still refetches appropriately when tokens become available (you already use `enabled: !tokenLoading`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines 381 to 405
// When a user token is present, build a user-scoped Octokit per integration
// config and call addGithubTokenRepositories with it. This makes
// listForAuthenticatedUser return only repos the user personally has access to.
// When absent, fall through to the existing server-credential path.
if (userTokens && Object.keys(userTokens).length > 0) {
const { errors: allErrors, totalCount } =
await this.fetchUserTokenGithubIntegrationRepositories(
userTokens,
(userOctokit, userCredential, dataFetchErrors) =>
addGithubTokenRepositories(
{ logger: this.logger },
userOctokit,
userCredential,
repositories,
dataFetchErrors,
{ search, pageNumber, pageSize },
),
);
const repoList = Array.from(repositories.values());
return { repositories: repoList, errors: allErrors, totalCount };
}

const result = await fetchFromAllIntegrations(
{
logger: this.logger,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Repo list falls back server 📎 Requirement gap ⛨ Security

When no X-SCM-Tokens header is provided (e.g., ScmAuthApi not registered), the frontend omits
user tokens and the backend falls through to server-wide integration credentials for repository
listing. This can return repositories beyond what the currently logged-in user can access, violating
the user-scoped listing requirement.
Agent Prompt
## Issue description
Repository listing can fall back to server-wide integration credentials when `X-SCM-Tokens` is absent/empty, which can expose repositories outside the current user's access.

## Issue Context
Compliance requires the Bulk Import GitHub repo list to be scoped to the currently logged-in user. Today, user tokens are optional and the backend falls back to server credentials when tokens are unavailable.

## Fix Focus Areas
- workspaces/bulk-import/plugins/bulk-import/src/hooks/useRepositories.ts[73-106]
- workspaces/bulk-import/plugins/bulk-import/src/api/BulkImportBackendClient.ts[118-137]
- workspaces/bulk-import/plugins/bulk-import-backend/src/github/githubApiService.ts[373-409]
- workspaces/bulk-import/plugins/bulk-import-backend/src/service/router.ts[138-176]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +304 to +306
- **`scm-hosts-read`**: tracks `GET` requests to the `/scm-hosts` endpoint, which returns the list of configured GitHub and GitLab integration host URLs.

- **`org-read`**: tracks `GET` requests to the `/organizations` endpoint, which returns the list of organizations accessible from all configured SCM Integrations (GitHub and GitLab).
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. /scm-hosts audit event mismatch 📎 Requirement gap ⚙ Maintainability

Backend documentation says /scm-hosts emits scm-hosts-read, but the router actually emits the
event id scm-read. This makes the documentation inaccurate for the new behavior.
Agent Prompt
## Issue description
The README documents the `/scm-hosts` audit event id as `scm-hosts-read`, but the implementation emits `scm-read`.

## Issue Context
This PR adds the `/scm-hosts` endpoint and updates documentation; the documentation must accurately reflect emitted audit events.

## Fix Focus Areas
- workspaces/bulk-import/plugins/bulk-import-backend/README.md[303-306]
- workspaces/bulk-import/plugins/bulk-import-backend/src/service/router.ts[805-807]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +167 to +176
function extractUserTokens(
headers:
| Paths.FindAllRepositories.HeaderParameters
| Paths.FindRepositoriesByOrganization.HeaderParameters,
logger: LoggerService,
): Record<string, string> | undefined {
const raw = headers['x-scm-tokens'] as string | undefined;
delete headers['x-scm-tokens']; // consumed; strip before any logging path
return parseScmTokensHeader(raw, logger);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Tokens logged in audits 🐞 Bug ⛨ Security

Audit events are created with the full Express request object, so the new x-scm-tokens header
(containing user OAuth tokens) can be persisted in audit logs/events. The header is only deleted
from a copied header object, leaving req.headers unchanged when auditing occurs.
Agent Prompt
### Issue description
`x-scm-tokens` contains user OAuth access tokens but is currently included in the Express `req` that is passed into `auditCreateEvent`, which can persist credentials in audit logs.

### Issue Context
The current code deletes `x-scm-tokens` only from a copied headers object (not `req.headers`) and does so inside specific handlers, after the router-level audit middleware already created the audit event.

### Fix Focus Areas
- workspaces/bulk-import/plugins/bulk-import-backend/src/service/router.ts[131-176]
- workspaces/bulk-import/plugins/bulk-import-backend/src/service/router.ts[752-787]

### Implementation guidance
- Parse and validate `x-scm-tokens` in an early middleware that runs **before** `permissionCheck` and before the audit middleware.
- After extracting, immediately `delete req.headers['x-scm-tokens']` (and also handle the case where it may be `string[]`).
- Store the parsed token map in a safe per-request location (e.g., `res.locals.scmTokens` or a typed request extension) and use that in the repository/org-repo handlers instead of reading from headers later.
- Ensure audit events never contain the raw token string.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +613 to +621
xSCMTokensHeaderParam:
in: header
name: x-scm-tokens
description: >
Optional JSON-encoded map of SCM host URL to user authentication token.
Used to fetch repositories on behalf of the user for each configured SCM host.
required: false
schema:
$ref: '#/components/schemas/SCMTokenMap'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

4. Openapi header type mismatch 🐞 Bug ✓ Correctness

The OpenAPI spec defines x-scm-tokens as an object schema (SCMTokenMap), but the implementation
expects a JSON-encoded string header and JSON.parse’s it. With OpenAPIBackend validation enabled,
sending a string header where the spec expects an object can cause validationFail (400) and break
on-behalf-of requests.
Agent Prompt
### Issue description
The OpenAPI schema models `x-scm-tokens` as an `object` (`SCMTokenMap`), but HTTP headers are strings and the server expects a JSON-encoded string and parses it with `JSON.parse`. With OpenAPIBackend request validation enabled, this schema mismatch can cause 400 validation failures when the header is present.

### Issue Context
The backend explicitly parses the header as JSON text; the schema should reflect that wire format.

### Fix Focus Areas
- workspaces/bulk-import/plugins/bulk-import-backend/src/schema/openapi.yaml[613-621]
- workspaces/bulk-import/plugins/bulk-import-backend/src/schema/openapi.yaml[716-731]
- workspaces/bulk-import/plugins/bulk-import-backend/src/generated/openapidocument.ts[1031-1039]
- workspaces/bulk-import/plugins/bulk-import-backend/src/generated/openapi.d.ts[30-41]

### Implementation guidance
- Change `xSCMTokensHeaderParam.schema` to `type: string` (and update description/example to indicate it is JSON).
  - Optionally keep `SCMTokenMap` schema for documentation purposes, but do not reference it as a header parameter schema unless you also implement OpenAPI object header serialization.
- Regenerate `openapidocument.ts` and `openapi.d.ts` so generated types match the actual string header.
- Keep server-side JSON parsing/validation as-is (or move it earlier per the audit fix).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +116 to +136
const tokenGeneration = useMemo(
() =>
scmAuthTokens
? Object.entries(scmAuthTokens)
.sort(([a], [b]) => a.localeCompare(b))
.map(([k, v]) => `${k}=${v}`)
.join(',')
: '',
[scmAuthTokens],
);

const {
data: value,
error,
isLoading: isQueryLoading,
} = useQuery(
[options?.showOrganizations ? 'organizations' : 'repositories', options],
[
options?.showOrganizations ? 'organizations' : 'repositories',
options,
tokenGeneration,
],
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

5. Token in query key 🐞 Bug ⛨ Security

The frontend includes raw OAuth token values in the React Query key, which can surface in React
Query devtools and other debugging/telemetry that logs query keys. This increases the risk of
accidental credential exposure in the browser.
Agent Prompt
### Issue description
OAuth token values are embedded in the React Query key (`tokenGeneration`), which can be exposed via devtools/debugging/logging of query keys.

### Issue Context
The query key only needs to change when the *effective auth context* changes; it should not contain secrets.

### Fix Focus Areas
- workspaces/bulk-import/plugins/bulk-import/src/hooks/useRepositories.ts[116-143]

### Implementation guidance
- Replace `tokenGeneration` with a non-secret discriminator, e.g.:
  - list of host URLs only: `Object.keys(scmAuthTokens ?? {}).sort().join(',')`
  - or a stable boolean/enum: `hasScmAuthTokens` plus `approvalTool`
  - or a one-way hash that does not include raw tokens (if you truly need to detect token changes)
- Ensure the query still refetches appropriately when tokens become available (you already use `enabled: !tokenLoading`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@rhdh-gh-app
Copy link
Copy Markdown

rhdh-gh-app Bot commented Mar 30, 2026

Important

This PR includes changes that affect public-facing API. Please ensure you are adding/updating documentation for new features or behavior.

Changed Packages

Package Name Package Path Changeset Bump Current Version
@red-hat-developer-hub/backstage-plugin-bulk-import-backend workspaces/bulk-import/plugins/bulk-import-backend minor v7.2.1
@red-hat-developer-hub/backstage-plugin-bulk-import workspaces/bulk-import/plugins/bulk-import minor v7.2.1

@PatAKnight PatAKnight changed the title On behalf of feat(bulk-import): add support for on-hehalf-of user access Mar 30, 2026
@PatAKnight PatAKnight force-pushed the on-behalf-of branch 2 times, most recently from 1ca662a to 534b652 Compare March 31, 2026 19:20
Copy link
Copy Markdown
Contributor

@AndrienkoAleksandr AndrienkoAleksandr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested with "scaffolder", "orchestrator" and "open-pull-requests". It works.

Signed-off-by: Patrick Knight <pknight@redhat.com>
Signed-off-by: Patrick Knight <pknight@redhat.com>
Signed-off-by: Patrick Knight <pknight@redhat.com>
Signed-off-by: Patrick Knight <pknight@redhat.com>
Signed-off-by: Patrick Knight <pknight@redhat.com>
Signed-off-by: Patrick Knight <pknight@redhat.com>
Signed-off-by: Patrick Knight <pknight@redhat.com>
Signed-off-by: Patrick Knight <pknight@redhat.com>
Signed-off-by: Patrick Knight <pknight@redhat.com>
Signed-off-by: Patrick Knight <pknight@redhat.com>
…tActionPath

Signed-off-by: Patrick Knight <pknight@redhat.com>
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Apr 7, 2026

@PatAKnight PatAKnight merged commit a1ae6d2 into redhat-developer:main Apr 8, 2026
11 checks passed
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.

2 participants