GitLab Grape OpenAPI

[!IMPORTANT] Internal use only. This gem exists to generate the OpenAPI 3.0 spec for the GitLab Rails monorepo and is not intended for use outside of GitLab.

  • It is published to rubygems.org only so the monorepo's Gemfile can depend on it — not as a general-purpose Grape → OpenAPI tool.
  • The public API, configuration DSL, and generated output may change in any release, including patch releases. There is no semantic-versioning contract.
  • No external support is provided. Issues and merge requests from outside GitLab may be closed without review.
  • Feature work is driven by the needs of gitlab-org/gitlab; capabilities that aren't needed there will not be added.

Internal gem for generating OpenAPI 3.0 specifications from Grape API definitions, used by gitlab-org/gitlab to publish its REST API reference.

Installation

Add to your Gemfile:

gem 'gitlab-grape-openapi'

Then run:

bundle install

Configuration

Configure the gem using the Gitlab::GrapeOpenapi.configure block, typically in an initializer:

Gitlab::GrapeOpenapi.configure do |config|
  # Required: API metadata
  config.info = Gitlab::GrapeOpenapi::Models::Info.new(
    title: 'My API',
    description: 'API description',
    version: 'v1',
    terms_of_service: 'https://example.com/terms'
  )

  # API path configuration
  config.api_prefix = "api"    # Default: "api"
  config.api_version = "v1"    # Default: "v1"

  # Server definitions
  config.servers = [
    Gitlab::GrapeOpenapi::Models::Server.new(
      url: 'https://{hostname}',
      description: "Production API",
      variables: {
        hostname: Gitlab::GrapeOpenapi::Models::ServerVariable.new(
          default: 'api.example.com',
          description: 'API hostname'
        )
      }
    )
  ]

  # Security schemes
  config.security_schemes = [
    Gitlab::GrapeOpenapi::Models::SecurityScheme.new(
      name: "bearerAuth",
      type: "http",
      scheme: "bearer"
    )
  ]

  # Exclude specific API classes from generation
  config.excluded_api_classes = [
    'API::Internal::Base',
    'API::Internal::Admin'
  ]

  # Override tag names for better display
  config.tag_overrides = {
    'Ci' => 'CI',
    'Oauth' => 'OAuth'
  }

  # Map Grape route settings to OpenAPI extensions
  config.annotations = {
    lifecycle: 'x-gitlab-lifecycle'
  }
end

Configuration Options

Option Type Default Description
info Models::Info nil API metadata (title, description, version, terms of service)
api_prefix String "api" URL prefix for API routes
api_version String "v1" API version string
servers Array<Models::Server> [] Server definitions for the API
security_schemes Array<Models::SecurityScheme> [] Authentication/authorization schemes
excluded_api_classes Array<String> [] API class names to exclude from generation
tag_overrides Hash {} Map of tag names to their display overrides
annotations Hash {} Map of Grape route settings to OpenAPI extension names

Annotations

The annotations configuration maps Grape route settings to OpenAPI vendor extensions. For example:

config.annotations = {
  lifecycle: 'x-gitlab-lifecycle'
}

When a Grape endpoint has:

```ruby
route_setting :lifecycle, 'mature'

The generated OpenAPI spec will include:

x-gitlab-lifecycle: mature

Usage

Generating an OpenAPI Specification

# Load all API and entity classes
Rails.application.eager_load!

api_classes = API::Base.descendants
entity_classes = Grape::Entity.descendants

# Generate the specification
spec = Gitlab::GrapeOpenapi.generate(
  api_classes: api_classes,
  entity_classes: entity_classes
)

# Output as JSON
File.write('openapi.json', JSON.pretty_generate(spec))

# Or as YAML
require 'yaml'
File.write('openapi.yaml', spec.to_yaml)

Usage with gitlab-org/gitlab

  1. Start a Rails console in your GDK:
   cd ~/gdk/gitlab
   rails console
  1. Generate the OpenAPI specification:
   Rails.application.eager_load!
   api_classes = API::Base.descendants
   entity_classes = Grape::Entity.descendants
   spec = Gitlab::GrapeOpenapi.generate(api_classes: api_classes, entity_classes: entity_classes)
   File.write(Rails.root.join('tmp', 'openapi.json'), JSON.pretty_generate(spec))
  1. The spec will be saved to tmp/openapi.json in your GitLab directory.

Architecture

The gem follows a converter-based architecture:

Generator
├── TagConverter        - Extracts tags from API classes
├── EntityConverter     - Converts Grape::Entity to OpenAPI schemas
├── PathConverter       - Converts routes to OpenAPI paths
│   ├── OperationConverter  - Converts individual endpoints
│   ├── ParameterConverter  - Converts endpoint parameters
│   ├── ResponseConverter   - Converts endpoint responses
│   └── RequestBodyConverter - Converts request bodies
└── TypeResolver        - Maps Ruby/Grape types to OpenAPI types

Registries

  • SchemaRegistry - Tracks converted entity schemas
  • RequestBodyRegistry - Tracks request body schemas
  • TagRegistry - Tracks API tags

Development

bundle install
bundle exec rspec

Running Tests

bundle exec rspec

Linting

bundle exec rubocop

Contributing

This gem is maintained by GitLab's API Platform team for internal use. External contributions are not actively solicited; issues and merge requests opened by non-GitLab contributors may be closed without review. GitLab team members should follow the standard contribution guidelines — see the project page.

License

Released under the MIT License.