Roadie Backstage Plugins

repository·main·Indexed 43 days ago

https://github.com/roadiehq/roadie-backstage-plugins

A collection of Backstage plugins developed and maintained by Roadie, including integrations for AWS and Argo CD. The set provides backend implementation details, configuration guides for authentication (including Azure OIDC), and instructions for integrating plugins into the Backstage backend system using packages like @roadiehq/backstage-plugin-aws-backend and @roadiehq/backstage-plugin-argo-cd-backend.

Tokens
132.7K
Snippets
505
Records
634
Agent score
56%

What's inside Roadie Backstage Plugins

  1. Understand the status of @roadiehq/rag-ai-node

    main

    The @roadiehq/rag-ai-node package is a reference implementation only. It is provided for demonstration and educational purposes to show how RAG (Retrieval-Augmented Generation) AI backend modules can be structured.

    Important Note: Roadie provides minimal support for these components and does not actively maintain or update them. Use them as a guide for building your own implementation rather than as a production-ready dependency.

  2. Configure AWS Lambda Authentication and Role ARN

    main

    The plugin requires the @roadiehq/backstage-plugin-aws-auth backend plugin to be installed. The plugin requests temporary credentials from the backend via /api/aws/credentials.

    If you need to pull Lambda information using a specific IAM role, you can pass a roleArn prop to the EntityAWSLambdaOverviewCard. The AWS user must have sts:AssumeRole permissions for the provided ARN.

    <EntityAWSLambdaOverviewCard
      roleArn={'arn:aws:iam::000000000000:role/roleName'}
    />
  3. How the ArgoCD node library architecture works

    main

    This package follows the standard Backstage -node library pattern. It contains only the public interface and service reference, with no implementation code or HTTP handlers.

    • @roadiehq/backstage-plugin-argo-cd-node: The package you depend on. It provides the ArgoServiceApi interface and the argocdServiceRef service reference.
    • @roadiehq/backstage-plugin-argo-cd-backend: The package that registers the actual implementation of ArgoService (which implements ArgoServiceApi) and depends on the -node library.
  4. Configure the GitHub Readme path via annotations

    main

    By default, the plugin uses the github.com/project-slug annotation to locate the root README.md. If you are working in a monorepo and need to point to a specific file, use the github.com/project-readme-path annotation in your entity metadata.

    Example annotation: 'github.com/project-readme-path': 'packages/sub-module/README.md'

  5. Implement custom Okta entity providers

    main

    If you need to customize how Okta users and groups are ingested into the Backstage catalog, you can implement your own entity provider by using the EntityProvider interface. You can choose between three main provider types:

    1. OktaOrgEntityProvider: Loads both users and groups together.
    2. OktaUserEntityProvider: Loads only users.
    3. OktaGroupEntityProvider: Loads only groups.

    Note: You must use either the default entity providers or your custom ones, not both simultaneously. To use a custom provider, you must register it as a Backstage module and add it to your backend using backend.add() while ensuring the default Okta provider is removed or commented out.

    import { createBackendModule, coreServices } from '@backstage/backend-plugin-api';
    import { oktaCatalogBackendEntityProviderFactoryExtensionPoint, EntityProviderFactory, OktaOrgEntityProvider } from '@roadiehq/catalog-backend-module-okta/new-backend';
    import { Config } from '@backstage/config';
    
    export const oktaOrgEntityProviderModule = createBackendModule({
      pluginId: 'catalog',
      moduleId: 'default-okta-org-entity-provider',
      register(env) {
        env.registerInit({
          deps: {
            provider: oktaCatalogBackendEntityProviderFactoryExtensionPoint,
            logger: coreServices.logger,
          },
          async init({ provider, logger }) {
            const factory: EntityProviderFactory = (oktaConfig: Config) =>
              OktaOrgEntityProvider.fromConfig(oktaConfig, {
                logger: logger,
                userNamingStrategy: 'strip-domain-email',
                groupNamingStrategy: 'kebab-case-name',
              });
    
            provider.setEntityProviderFactory(factory);
          },
        });
      },
    });
    
    // In packages/backend/src/index.ts:
    // backend.add(import('@roadiehq/catalog-backend-module-okta/default-provider-factory')); // Remove/Comment this
    backend.add(oktaOrgEntityProviderModule);
  6. How the RAG AI retrieval pipeline works

    main

    The Roadie RAG AI backend utilizes a retrieval pipeline to augment queries sent to configured LLMs.

    Core Workflow

    1. Retrieval: The pipeline retrieves information based on queries and other metadata.
    2. Processing: Information is processed and sorted.
    3. Augmentation: The processed data is added to the query prompt sent to the LLM.

    Configuration Modes

    • Full Pipeline: Retrieves and processes data to provide context to the LLM.
    • Pass-through Mode: The pipeline runs without adding additional context, allowing users to interact with the configured LLMs directly.
    • Customizable Implementation: The module is designed to be extended by injecting use-case specific implementations for:
      • Embeddings
      • Retrieval
      • Post-processing
      • Routing

    Best Practices for Extension

    To build a robust RAG pipeline, it is recommended to:

    • Implement Routers: Use routers to define which specific retrievers should be used for different types of augmentation information.
    • Use Post-processors: Implement post-processing logic to rerank, sort, and manipulate retrieved information before it reaches the LLM.
  7. Ensure idempotency for http:backstage:request during task recovery

    main

    When using Backstage's experimental task recovery (spec.EXPERIMENTAL_recovery.EXPERIMENTAL_strategy: startOver), tasks that are interrupted are restarted from the beginning. This can cause non-idempotent actions (like creating a Jira ticket) to be duplicated.

    To prevent this, use the idempotencyKey input. This wraps the request in a checkpoint:

    • The request is executed at most once per task.
    • On a restart, the cached response is returned instead of re-sending the request.

    The idempotencyKey must be a stable and unique string within the template.

    If idempotencyKey is omitted, the request will be sent every time the task runs.

    steps:
      - id: create_jira_ticket
        name: Create Jira ticket
        action: http:backstage:request
        input:
          method: 'POST'
          path: '/proxy/jira/api/rest/api/latest/issue'
          idempotencyKey: 'jira.create.parent'
          headers:
            content-type: 'application/json'
          body:
            fields:
              project: { key: 'PROJ' }
              summary: 'Created from Backstage'
              issuetype: { name: 'Task' }
  8. Authenticate with ArgoCD

    main

    The plugin supports four authentication methods with different priority levels:

    1. Global Credentials (Lowest Priority): Set username and password directly under the argocd key. These are used for all instances by default.
    2. Instance-specific Credentials: Set username and password within a specific instance in appLocatorMethods. This overrides the global credentials.
    3. Instance-specific Token (Highest Priority): Set a token within a specific instance. This overrides both global credentials and instance-specific username/password.
    4. Azure OIDC (Lowest Priority): Use oidcConfig with provider: azure and a providerConfigKey pointing to your Azure configuration. This is used if no other login options are available.
  9. Build iframe URLs from entity annotations

    main

    Instead of providing a full URL in the src prop, you can use srcFromAnnotation to pull an identifier from an entity's annotation and transform it into a full URL.

    Use the transform prop to define how the annotation value is processed. The transform function receives (value, entity) where value is the annotation string and entity is the Backstage entity object.

    Common transformation patterns include:

    • Prefix only: Using wrapAnnotation('prefix') to prepend a base URL.
    • Prefix and Suffix: Using wrapAnnotation('prefix', 'suffix') to wrap the value.
    • Template: Using intoTemplate('url/with/${value}/suffix') to embed the value anywhere.
    • Custom: A manual function for complex logic involving entity metadata.

    Note: The resulting URL must be HTTPS and must be included in the iframe.allowList configuration.

    import {
      EntityIFrameCard,
      wrapAnnotation,
      intoTemplate,
    } from '@roadiehq/backstage-plugin-iframe';
    
    // 1) Prefix only: https://host/prefix/${annotation_value}
    <EntityIFrameCard
      srcFromAnnotation="grafana/dashboard-id"
      transform={wrapAnnotation('https://grafana.example.com/d/')}
    />
    
    // 2) Prefix + suffix: https://host/foo/${annotation_value}/extra
    <EntityIFrameCard
      srcFromAnnotation="my-org/widget-id"
      transform={wrapAnnotation('https://example.com/foo/', '/extra')}
    />
    
    // 3) Free-form template
    <EntityIFrameCard
      srcFromAnnotation="my-org/widget-id"
      transform={intoTemplate('https://example.com/foo/${value}/extra')}
    />
    
    // 4) Custom transform using entity context
    <EntityIFrameCard
      srcFromAnnotation="grafana/dashboard-id"
      transform={(value, entity) =>
        `https://grafana.example.com/d/${value}?var-service=${entity.metadata.name}`
      }
    />