Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hive Gateway benchmark table #6482

Merged
merged 11 commits into from
Feb 11, 2025
Merged

Hive Gateway benchmark table #6482

merged 11 commits into from
Feb 11, 2025

Conversation

hasparus
Copy link
Collaborator

@hasparus hasparus commented Feb 6, 2025

Background

image

Description

Added the benchmark table.

I have thoughts on why it's display: block by default, and I'd potentially do some work on Components side to make it easier to use, but it can wait. Forgive my todo comments.

);
}

function XIcon(props: React.SVGProps<SVGSVGElement>) {
Copy link
Collaborator Author

@hasparus hasparus Feb 6, 2025

Choose a reason for hiding this comment

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

this is "x test failed", not "𝕏 the everything app"

@hasparus hasparus requested a review from saihaj February 6, 2025 16:10
Copy link
Contributor

github-actions bot commented Feb 6, 2025

💻 Website Preview

The latest changes are available as preview in: https://f0ce1f44.hive-landing-page.pages.dev

Copy link
Contributor

coderabbitai bot commented Feb 6, 2025

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Integrated enhanced error handling to improve data display reliability.
    • Introduced a dynamic benchmark section that presents gateway benchmark data interactively.
    • Added components for rendering benchmark details with computed compatibility percentages and color-coded visual indicators.
    • Rolled out new visual icons to clearly represent successful and unsuccessful benchmark outcomes.

Walkthrough

The pull request introduces several new components and enhancements to the gateway documentation page. An error boundary is now integrated into the page to wrap the benchmarks section, ensuring that any runtime errors in its child components are caught and handled gracefully. Additionally, a suite of new components has been added to fetch and render benchmark data in a table format. This includes UI components for visualizing data such as benchmark results and icons, along with a shared constants module for color tones. The overall updates aim to improve error handling and the dynamic presentation of benchmark information.

Changes

File(s) Change Summary
packages/web/docs/src/app/gateway/page.tsx Added imports for ErrorBoundary and FederationCompatibleBenchmarksSection; wrapped the benchmarks section in the ErrorBoundary with a null fallback for error handling.
packages/web/docs/src/app/gateway/federation-compatible-benchmarks/* New components and assets introduced:
- BenchmarkTableBody for asynchronously fetching and rendering benchmark data in a table.
- FederationCompatibleBenchmarksSection to display benchmark information with a header, table, and legend.
- functionalTones constant for color coding.
- CheckmarkIcon and XIcon icon components for visual indicators.
packages/web/docs/src/components/error-boundary.ts New ErrorBoundary class component added to catch JavaScript errors in its child components, log errors, and display a fallback UI when an error is encountered.

Sequence Diagram(s)

sequenceDiagram
  participant P as HiveGatewayPage
  participant EB as ErrorBoundary
  participant F as FederationCompatibleBenchmarksSection
  participant S as Suspense
  participant B as BenchmarkTableBody
  participant API as Benchmark Data API

  P->>EB: Render with benchmarks section wrapped
  EB->>F: Render FederationCompatibleBenchmarksSection
  F->>S: Initiate Suspense for asynchronous data loading
  S->>B: Render BenchmarkTableBody (fetching benchmark data)
  B->>API: Request benchmark data
  API-->>B: Send benchmark data
  B-->>S: Return rendered table rows
  S-->>F: Complete table rendering with data
  F-->>EB: Return complete benchmarks section
  EB-->>P: Render final UI
  Note over EB: If error occurs, display fallback UI
Loading

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (3)
packages/web/docs/src/app/gateway/federation-compatible-benchmarks.tsx (3)

3-41: Consider moving static data to a separate file.

The benchmark data could be moved to a separate file (e.g., benchmark-data.ts) to improve maintainability and separation of concerns.

+// benchmark-data.ts
+export interface BenchmarkDatum {
+  name: string;
+  compatibility: number;
+  cases: { passed: number; failed: number };
+  suites: { passed: number; failed: number };
+}
+
+export const data: BenchmarkDatum[] = [
+  // ... existing data
+];

-interface BenchmarkDatum {
-  // ... interface definition
-}
-
-const data: BenchmarkDatum[] = [
-  // ... data array
-];

122-123: Track the Components bug in the issue tracker.

The TODO comment about a bug in Components should be tracked in the issue tracker for proper follow-up.

Would you like me to create an issue to track this Components bug?


124-125: Extract magic numbers in CSS classes to Tailwind configuration.

The hardcoded padding values (pl-5) should be defined as custom spacing in the Tailwind configuration for better maintainability.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6bef900 and 4ae71f3.

📒 Files selected for processing (2)
  • packages/web/docs/src/app/gateway/federation-compatible-benchmarks.tsx (1 hunks)
  • packages/web/docs/src/app/gateway/page.tsx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`packages/web/docs/**`: The main landing page and documentat...

packages/web/docs/**: The main landing page and documentation website. It's built using TypeScript, Tailwind, NextJS and Nextra.

In PRs that adds a new feature to the product, we would like to make sure that the PR includes the following:

  • Up to date documentation in packages/web/docs/src/content
  • A product update in packages/web/docs/src/app/product-updates
  • packages/web/docs/src/app/gateway/page.tsx
  • packages/web/docs/src/app/gateway/federation-compatible-benchmarks.tsx
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: website-preview / deployment
  • GitHub Check: test / unit
  • GitHub Check: typescript / typecheck
  • GitHub Check: static-analysis / analyze (typescript)
  • GitHub Check: static-analysis / analyze (javascript)
  • GitHub Check: build / dockerize (linux/arm64)
  • GitHub Check: test / db-migrations
  • GitHub Check: build / dockerize (linux/amd64)
  • GitHub Check: code-style / eslint-and-prettier
  • GitHub Check: alpha / cli-artifacts
  • GitHub Check: SonarCloud
🔇 Additional comments (2)
packages/web/docs/src/app/gateway/page.tsx (1)

13-13: LGTM!

The new component is correctly imported and integrated into the page layout.

Also applies to: 58-58

packages/web/docs/src/app/gateway/federation-compatible-benchmarks.tsx (1)

1-1: Add required documentation updates.

According to the coding guidelines, new features should include:

  • Documentation updates in packages/web/docs/src/content
  • Product update in packages/web/docs/src/app/product-updates

Please add the necessary documentation for this new benchmark table feature.

@hasparus
Copy link
Collaborator Author

hasparus commented Feb 6, 2025

@coderabbitai

The benchmark data could be moved to a separate file (e.g., benchmark-data.ts) to improve maintainability and separation of concerns.

If you bring separation of concerns in favor of colocation again, I'm gonna find your servers and fill their whole memory with copies of https://kentcdodds.com/blog/colocation. Read the blog post.

Copy link
Contributor

coderabbitai bot commented Feb 6, 2025

@hasparus You're absolutely right, I apologize. Colocation is indeed a better practice here since the benchmark data is tightly coupled with its usage in the component. I'll remember this for future reviews.


✏️ Learnings added
Learnt from: hasparus
URL: https://github.com/graphql-hive/console/pull/6482

Timestamp: 2025-02-06T16:18:55.539Z
Learning: Prefer colocation over separation of concerns when the data/code is only used in one place. Keep things close to where they're used as per https://kentcdodds.com/blog/colocation principles.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

✅ Actions performed

Comments resolved.

Copy link
Contributor

github-actions bot commented Feb 6, 2025

🐋 This PR was built and pushed to the following Docker images:

Targets: build

Platforms: linux/arm64

Image Tag: 59ea95978a8daa4ed605f710aec6c81d91fcad64

Docker Bake metadata
{
"app": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/api/health",
          "build-arg:IMAGE_DESCRIPTION": "The app of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/app",
          "build-arg:PORT": "3000",
          "build-arg:RELEASE": "59ea95978a8daa4ed605f710aec6c81d91fcad64",
          "build-arg:SERVICE_DIR_NAME": "@hive/app",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:dockerfile": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:shared": "j4at0utx5zqn9y3b756q0s3gi"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b488/builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b4880/17diy6cl0vlvks71dtfek2ch8",
  "containerimage.config.digest": "sha256:37eebfbc7ced54a5293151c258d7dc18ce9d062dcea190179be72bc4c05cb1ab",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:e4eef8decdf909a277e57458b5e6944c3ee6182f4bc6e6990249dc440b0b10ee",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:e4eef8decdf909a277e57458b5e6944c3ee6182f4bc6e6990249dc440b0b10ee",
  "image.name": "ghcr.io/graphql-hive/app:59ea95978a8daa4ed605f710aec6c81d91fcad64-arm64,ghcr.io/graphql-hive/app:hive_gateway_table-arm64"
},
"buildx.build.warnings": [
  {
    "vertex": "sha256:2b6947c2f77aae5530ad9a0d9fe84297a1e3ce0952444751572d5e082606a77f",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRJTUFHRV9USVRMRScgKGxpbmUgMTIp",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 12
        },
        "end": {
          "line": 12
        }
      }
    ]
  },
  {
    "vertex": "sha256:240c241d6222b3d48ee04dff37e6d71600b6388b3f243fada66f6806107c945e",
    "level": 1,
    "short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDEwKQ==",
    "detail": [
      "TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
    "sourceInfo": {
      "filename": "migrations.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 10
        },
        "end": {
          "line": 10
        }
      }
    ]
  },
  {
    "vertex": "sha256:240c241d6222b3d48ee04dff37e6d71600b6388b3f243fada66f6806107c945e",
    "level": 1,
    "short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDEyKQ==",
    "detail": [
      "TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
    "sourceInfo": {
      "filename": "migrations.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 12
        },
        "end": {
          "line": 12
        }
      }
    ]
  },
  {
    "vertex": "sha256:240c241d6222b3d48ee04dff37e6d71600b6388b3f243fada66f6806107c945e",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRSRUxFQVNFJyAobGluZSAxMik=",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "migrations.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 12
        },
        "end": {
          "line": 12
        }
      }
    ]
  },
  {
    "vertex": "sha256:240c241d6222b3d48ee04dff37e6d71600b6388b3f243fada66f6806107c945e",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRJTUFHRV9ERVNDUklQVElPTicgKGxpbmUgMTcp",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "migrations.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 17
        },
        "end": {
          "line": 17
        }
      }
    ]
  },
  {
    "vertex": "sha256:2b6947c2f77aae5530ad9a0d9fe84297a1e3ce0952444751572d5e082606a77f",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRJTUFHRV9ERVNDUklQVElPTicgKGxpbmUgMTQp",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 14
        },
        "end": {
          "line": 14
        }
      }
    ]
  },
  {
    "vertex": "sha256:2b6947c2f77aae5530ad9a0d9fe84297a1e3ce0952444751572d5e082606a77f",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRQT1JUJyAobGluZSAyMik=",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 22
        },
        "end": {
          "line": 22
        }
      }
    ]
  },
  {
    "vertex": "sha256:2b6947c2f77aae5530ad9a0d9fe84297a1e3ce0952444751572d5e082606a77f",
    "level": 1,
    "short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDIyKQ==",
    "detail": [
      "TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 22
        },
        "end": {
          "line": 22
        }
      }
    ]
  },
  {
    "vertex": "sha256:240c241d6222b3d48ee04dff37e6d71600b6388b3f243fada66f6806107c945e",
    "level": 1,
    "short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDExKQ==",
    "detail": [
      "TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
    "sourceInfo": {
      "filename": "migrations.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 11
        },
        "end": {
          "line": 11
        }
      }
    ]
  },
  {
    "vertex": "sha256:2b6947c2f77aae5530ad9a0d9fe84297a1e3ce0952444751572d5e082606a77f",
    "level": 1,
    "short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDIwKQ==",
    "detail": [
      "TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 20
        },
        "end": {
          "line": 20
        }
      }
    ]
  },
  {
    "vertex": "sha256:2b6947c2f77aae5530ad9a0d9fe84297a1e3ce0952444751572d5e082606a77f",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRSRUxFQVNFJyAobGluZSAyMSk=",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 21
        },
        "end": {
          "line": 21
        }
      }
    ]
  },
  {
    "vertex": "sha256:2b6947c2f77aae5530ad9a0d9fe84297a1e3ce0952444751572d5e082606a77f",
    "level": 1,
    "short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDIxKQ==",
    "detail": [
      "TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 21
        },
        "end": {
          "line": 21
        }
      }
    ]
  },
  {
    "vertex": "sha256:240c241d6222b3d48ee04dff37e6d71600b6388b3f243fada66f6806107c945e",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRJTUFHRV9USVRMRScgKGxpbmUgMTUp",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "migrations.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 15
        },
        "end": {
          "line": 15
        }
      }
    ]
  },
  {
    "vertex": "sha256:2b6947c2f77aae5530ad9a0d9fe84297a1e3ce0952444751572d5e082606a77f",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRSRUxFQVNFJyAobGluZSAxMyk=",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 13
        },
        "end": {
          "line": 13
        }
      }
    ]
  }
],
"composition-federation-2": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "Federation 2 Composition Service for GraphQL Hive.",
          "build-arg:IMAGE_TITLE": "graphql-hive/composition-federation-2",
          "build-arg:PORT": "3069",
          "build-arg:RELEASE": "59ea95978a8daa4ed605f710aec6c81d91fcad64",
          "build-arg:SERVICE_DIR_NAME": "@hive/external-composition",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:dockerfile": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:shared": "j4at0utx5zqn9y3b756q0s3gi"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b488/builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b4880/klve80pi8mv9rz82maooitsgn",
  "containerimage.config.digest": "sha256:45558712cca5c9fdeca17e73d94f6f7cdb9f7ef6c47a730c83fc99836918e78c",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:22767e3660e26fd798b3df4da732ffdd63bce1850d02e40850583363daf96b26",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:22767e3660e26fd798b3df4da732ffdd63bce1850d02e40850583363daf96b26",
  "image.name": "ghcr.io/graphql-hive/composition-federation-2:59ea95978a8daa4ed605f710aec6c81d91fcad64-arm64,ghcr.io/graphql-hive/composition-federation-2:hive_gateway_table-arm64"
},
"emails": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The emails service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/emails",
          "build-arg:PORT": "3006",
          "build-arg:RELEASE": "59ea95978a8daa4ed605f710aec6c81d91fcad64",
          "build-arg:SERVICE_DIR_NAME": "@hive/emails",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:dockerfile": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:shared": "j4at0utx5zqn9y3b756q0s3gi"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b488/builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b4880/df9vag9rhpnhx44evkjf96wa5",
  "containerimage.config.digest": "sha256:7a075b31ee64ceba607be4aae9868a2e4166e90ef14aa41a6322df8fed2fce55",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:556f97d90cba89dc2295dfb2a6a67d705057853a1295d4417986ae72143f2b56",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:556f97d90cba89dc2295dfb2a6a67d705057853a1295d4417986ae72143f2b56",
  "image.name": "ghcr.io/graphql-hive/emails:59ea95978a8daa4ed605f710aec6c81d91fcad64-arm64,ghcr.io/graphql-hive/emails:hive_gateway_table-arm64"
},
"policy": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The policy service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/policy",
          "build-arg:PORT": "3012",
          "build-arg:RELEASE": "59ea95978a8daa4ed605f710aec6c81d91fcad64",
          "build-arg:SERVICE_DIR_NAME": "@hive/policy",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:dockerfile": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:shared": "j4at0utx5zqn9y3b756q0s3gi"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b488/builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b4880/qjqwfl0xep76fq9wy1c2uxty5",
  "containerimage.config.digest": "sha256:33fa9c97d84d3f3c8d3e164080e0c1b54ecc7475572eb89c4333776c0d7a1aea",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:955ee964def6defb75b9aa05dfc8efaa6d81fa920d3f0f43019ace56ed02f915",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:955ee964def6defb75b9aa05dfc8efaa6d81fa920d3f0f43019ace56ed02f915",
  "image.name": "ghcr.io/graphql-hive/policy:59ea95978a8daa4ed605f710aec6c81d91fcad64-arm64,ghcr.io/graphql-hive/policy:hive_gateway_table-arm64"
},
"rate-limit": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The rate limit service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/rate-limit",
          "build-arg:PORT": "3009",
          "build-arg:RELEASE": "59ea95978a8daa4ed605f710aec6c81d91fcad64",
          "build-arg:SERVICE_DIR_NAME": "@hive/rate-limit",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:dockerfile": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:shared": "j4at0utx5zqn9y3b756q0s3gi"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b488/builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b4880/jbsd7h3jqytppehr399xh9nzp",
  "containerimage.config.digest": "sha256:9d84f86cde2ebd99869563103c022286ca5b8b8a237ceaf58e4e4361ec410f80",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:af9ec8ecf59445179f2cc07bc5eeb0a6937c83f70fde078ae03b77cecbccca9f",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:af9ec8ecf59445179f2cc07bc5eeb0a6937c83f70fde078ae03b77cecbccca9f",
  "image.name": "ghcr.io/graphql-hive/rate-limit:59ea95978a8daa4ed605f710aec6c81d91fcad64-arm64,ghcr.io/graphql-hive/rate-limit:hive_gateway_table-arm64"
},
"schema": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The schema service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/schema",
          "build-arg:PORT": "3002",
          "build-arg:RELEASE": "59ea95978a8daa4ed605f710aec6c81d91fcad64",
          "build-arg:SERVICE_DIR_NAME": "@hive/schema",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:dockerfile": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:shared": "j4at0utx5zqn9y3b756q0s3gi"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b488/builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b4880/ldxyf6w5hc1sm1idrs8zhkb28",
  "containerimage.config.digest": "sha256:b8797902357d39c2894cfe44396088a50b1bc35f9b178f10586dc150b74070a9",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:d4cb3728abe08e05ec978d0140b32518a76596f848d0247493ea3a09e0dd3f08",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:d4cb3728abe08e05ec978d0140b32518a76596f848d0247493ea3a09e0dd3f08",
  "image.name": "ghcr.io/graphql-hive/schema:59ea95978a8daa4ed605f710aec6c81d91fcad64-arm64,ghcr.io/graphql-hive/schema:hive_gateway_table-arm64"
},
"server": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The server service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/server",
          "build-arg:PORT": "3001",
          "build-arg:RELEASE": "59ea95978a8daa4ed605f710aec6c81d91fcad64",
          "build-arg:SERVICE_DIR_NAME": "@hive/server",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:dockerfile": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:shared": "j4at0utx5zqn9y3b756q0s3gi"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b488/builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b4880/yvpa7q12q5l30hs14q4845pt7",
  "containerimage.config.digest": "sha256:03ccffd370a74cd68757749044ea1112a5760cc46af477e6bebadc56a362c603",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:0249909feabc5b3be21ace45bd2c1dae4fc7a004fbfbe26c2af4725b7731daa8",
    "size": 2076,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:0249909feabc5b3be21ace45bd2c1dae4fc7a004fbfbe26c2af4725b7731daa8",
  "image.name": "ghcr.io/graphql-hive/server:59ea95978a8daa4ed605f710aec6c81d91fcad64-arm64,ghcr.io/graphql-hive/server:hive_gateway_table-arm64"
},
"storage": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "migrations.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:IMAGE_DESCRIPTION": "The migrations service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/storage",
          "build-arg:RELEASE": "59ea95978a8daa4ed605f710aec6c81d91fcad64",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:dockerfile": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:shared": "j4at0utx5zqn9y3b756q0s3gi"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b488/builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b4880/75sk9zi401bdhrlmde3lxouan",
  "containerimage.config.digest": "sha256:123f0f7b1bf504b79208c70747709e97f624663f43b9a3950d1cc91daed74739",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:aedbd05c35644dfdc681677f3515c58c768bad6fdda1641780e131b45e7bb147",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:aedbd05c35644dfdc681677f3515c58c768bad6fdda1641780e131b45e7bb147",
  "image.name": "ghcr.io/graphql-hive/storage:59ea95978a8daa4ed605f710aec6c81d91fcad64-arm64,ghcr.io/graphql-hive/storage:hive_gateway_table-arm64"
},
"stripe-billing": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The stripe billing service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/stripe-billing",
          "build-arg:PORT": "3010",
          "build-arg:RELEASE": "59ea95978a8daa4ed605f710aec6c81d91fcad64",
          "build-arg:SERVICE_DIR_NAME": "@hive/stripe-billing",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:dockerfile": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:shared": "j4at0utx5zqn9y3b756q0s3gi"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b488/builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b4880/t1dhp2p1k9eknt8tm4e1y83ko",
  "containerimage.config.digest": "sha256:dff5f4ae9578a88d5b5d04e7fcacf9081a114d94ddcde8e5abcbbbbf2cdd0e4f",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:127e76ef9a9de340d37a189879622d0550cbd6931fc39516fc0e670ba3e64cf0",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:127e76ef9a9de340d37a189879622d0550cbd6931fc39516fc0e670ba3e64cf0",
  "image.name": "ghcr.io/graphql-hive/stripe-billing:59ea95978a8daa4ed605f710aec6c81d91fcad64-arm64,ghcr.io/graphql-hive/stripe-billing:hive_gateway_table-arm64"
},
"tokens": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The tokens service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/tokens",
          "build-arg:PORT": "3003",
          "build-arg:RELEASE": "59ea95978a8daa4ed605f710aec6c81d91fcad64",
          "build-arg:SERVICE_DIR_NAME": "@hive/tokens",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:dockerfile": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:shared": "j4at0utx5zqn9y3b756q0s3gi"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b488/builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b4880/x7ke38c77x79iw60ph51av53q",
  "containerimage.config.digest": "sha256:6afa09cc111f1e3eb3eb5379250bd03df281de2cded474a7f1b8431aa95786c5",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:ed5523480ef683400fb770f765857d9aa2e661cb88e951a3b5eb2d253145c0f2",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:ed5523480ef683400fb770f765857d9aa2e661cb88e951a3b5eb2d253145c0f2",
  "image.name": "ghcr.io/graphql-hive/tokens:59ea95978a8daa4ed605f710aec6c81d91fcad64-arm64,ghcr.io/graphql-hive/tokens:hive_gateway_table-arm64"
},
"usage": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The usage ingestor service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/usage",
          "build-arg:PORT": "3006",
          "build-arg:RELEASE": "59ea95978a8daa4ed605f710aec6c81d91fcad64",
          "build-arg:SERVICE_DIR_NAME": "@hive/usage",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:dockerfile": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:shared": "j4at0utx5zqn9y3b756q0s3gi"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b488/builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b4880/ow9lyy8c7k4svok31uwipehz2",
  "containerimage.config.digest": "sha256:2c9b73398b0ae49977558f1a0130b8e166602f828d63d9ba44f07b2c4b5f6043",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:22dd26f61cc24b1d69e53a7af761d04c827294961d1959f40fc736d0a16b87d4",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:22dd26f61cc24b1d69e53a7af761d04c827294961d1959f40fc736d0a16b87d4",
  "image.name": "ghcr.io/graphql-hive/usage:59ea95978a8daa4ed605f710aec6c81d91fcad64-arm64,ghcr.io/graphql-hive/usage:hive_gateway_table-arm64"
},
"usage-estimator": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The usage estimator service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/usage-estimator",
          "build-arg:PORT": "3008",
          "build-arg:RELEASE": "59ea95978a8daa4ed605f710aec6c81d91fcad64",
          "build-arg:SERVICE_DIR_NAME": "@hive/usage-estimator",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:dockerfile": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:shared": "j4at0utx5zqn9y3b756q0s3gi"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b488/builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b4880/l10yrpdy7cunx5mhg10w3f1uh",
  "containerimage.config.digest": "sha256:ab7907bbcbaf78de0d946f4c77e375f216ff5f6c359b5df29714861166b38de3",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:15c4403fcdf33bf8f55d9c5c8324cc630d81b244673d7bf3801468e5e5bd2bea",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:15c4403fcdf33bf8f55d9c5c8324cc630d81b244673d7bf3801468e5e5bd2bea",
  "image.name": "ghcr.io/graphql-hive/usage-estimator:59ea95978a8daa4ed605f710aec6c81d91fcad64-arm64,ghcr.io/graphql-hive/usage-estimator:hive_gateway_table-arm64"
},
"usage-ingestor": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The usage ingestor service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/usage-ingestor",
          "build-arg:PORT": "3007",
          "build-arg:RELEASE": "59ea95978a8daa4ed605f710aec6c81d91fcad64",
          "build-arg:SERVICE_DIR_NAME": "@hive/usage-ingestor",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:dockerfile": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:shared": "j4at0utx5zqn9y3b756q0s3gi"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b488/builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b4880/6gzceuhku7hs0p0f9htj0cg3q",
  "containerimage.config.digest": "sha256:39c5f7b4fe9a41fa120b78e4b9ef557d04fe2396310b1eff35869cae079bf8c5",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:e7975e2241d186a9ef5373be155058e1a923cb528b6e4ee2584d2c45cdb7e3c9",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:e7975e2241d186a9ef5373be155058e1a923cb528b6e4ee2584d2c45cdb7e3c9",
  "image.name": "ghcr.io/graphql-hive/usage-ingestor:59ea95978a8daa4ed605f710aec6c81d91fcad64-arm64,ghcr.io/graphql-hive/usage-ingestor:hive_gateway_table-arm64"
},
"webhooks": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The webhooks ingestor service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/webhooks",
          "build-arg:PORT": "3005",
          "build-arg:RELEASE": "59ea95978a8daa4ed605f710aec6c81d91fcad64",
          "build-arg:SERVICE_DIR_NAME": "@hive/webhooks",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:dockerfile": "j4at0utx5zqn9y3b756q0s3gi",
          "local-sessionid:shared": "j4at0utx5zqn9y3b756q0s3gi"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b488/builder-656c0f74-9f6c-4ca5-b3c6-dffa4a14b4880/6cxowrw3tppiovepkwd2vst3z",
  "containerimage.config.digest": "sha256:3eccbb90b5f7a165770e740d045ede2d3db75286b916012918cde7243287b569",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:e72766834b6a1c3a5e5ba4fdefce681615a8974dc515eae3d6c66d680cbab067",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:e72766834b6a1c3a5e5ba4fdefce681615a8974dc515eae3d6c66d680cbab067",
  "image.name": "ghcr.io/graphql-hive/webhooks:59ea95978a8daa4ed605f710aec6c81d91fcad64-arm64,ghcr.io/graphql-hive/webhooks:hive_gateway_table-arm64"
}
}

Copy link
Contributor

🚀 Snapshot Release (alpha)

The latest changes of this PR are available as alpha on npm (based on the declared changesets):

Package Version Info
@graphql-hive/apollo 0.37.1-alpha-20250210160726-8906495171843102b2ad864a2cb8fa16391a77cb npm ↗︎ unpkg ↗︎
@graphql-hive/cli 0.48.1-alpha-20250210160726-8906495171843102b2ad864a2cb8fa16391a77cb npm ↗︎ unpkg ↗︎
@graphql-hive/core 0.9.1-alpha-20250210160726-8906495171843102b2ad864a2cb8fa16391a77cb npm ↗︎ unpkg ↗︎
@graphql-hive/envelop 0.34.1-alpha-20250210160726-8906495171843102b2ad864a2cb8fa16391a77cb npm ↗︎ unpkg ↗︎
@graphql-hive/yoga 0.40.1-alpha-20250210160726-8906495171843102b2ad864a2cb8fa16391a77cb npm ↗︎ unpkg ↗︎


import { Component } from 'react';

export class ErrorBoundary extends Component<{
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It is a bit absurd that this ins't exported from React, but I guess people have different error tracking needs and not everybody just plugs console.error into some useful log sink.

Comment on lines +60 to +62
fallback={
// this section doesn't make sense if data didn't load, so we just unmount
null
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is needed in case the data.json was down. The promise rejects, and then React rips everything until this error boundary and renders this null.

Comment on lines +72 to +76
<tbody aria-busy>
<tr>
<td colSpan={4} className="bg-beige-100 h-[347.5px] animate-pulse cursor-wait" />
</tr>
</tbody>
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not the nicest skeleton I did, but I feel it's good enough.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (8)
packages/web/docs/src/app/gateway/federation-compatible-benchmarks/functional-tones.ts (2)

1-3: Consider tracking the TODO in an issue.

The comment about moving these colors to the design system as Tailwind classes should be tracked in an issue to ensure it's not forgotten.

Would you like me to create an issue to track this design system integration task?


4-10: Consider using CSS custom properties for color values.

While the color values are well-organized with semantic names, consider using CSS custom properties (variables) for better maintainability and theme support.

 export const functionalTones = {
-  criticalBright: '#FD3325',
-  criticalDark: ' #F81202',
-  warning: '#FE8830',
-  positiveBright: '#24D551',
-  positiveDark: '#1BA13D',
+  criticalBright: 'var(--color-critical-bright, #FD3325)',
+  criticalDark: 'var(--color-critical-dark, #F81202)',
+  warning: 'var(--color-warning, #FE8830)',
+  positiveBright: 'var(--color-positive-bright, #24D551)',
+  positiveDark: 'var(--color-positive-dark, #1BA13D)',
 };
packages/web/docs/src/components/error-boundary.ts (2)

11-14: Consider integrating with an error reporting service.

While console logging is helpful during development, consider integrating with an error reporting service for production environments.

 static getDerivedStateFromError(error: Error) {
-  console.error(error);
+  // TODO: Replace with your error reporting service
+  if (process.env.NODE_ENV === 'production') {
+    // errorReportingService.captureError(error);
+  } else {
+    console.error(error);
+  }
   return { hasError: true };
 }

16-18: Consider enhancing error information capture.

The componentDidCatch method could capture more context about the error to aid debugging.

 componentDidCatch(error: Error, info: { componentStack: string }) {
-  console.error(error, info);
+  const errorInfo = {
+    error: {
+      message: error.message,
+      name: error.name,
+      stack: error.stack,
+    },
+    componentStack: info.componentStack,
+  };
+  if (process.env.NODE_ENV === 'production') {
+    // errorReportingService.captureError(error, errorInfo);
+  } else {
+    console.error('Error caught by boundary:', errorInfo);
+  }
 }
packages/web/docs/src/app/gateway/federation-compatible-benchmarks/icons.tsx (1)

1-2: Document the rationale for custom icons.

The comment indicates these icons are different from the design system, but it would be helpful to document why custom icons are needed instead of using the existing ones.

-// these are different than CheckIcon and CloseIcon we have in the design system
+/**
+ * Custom icons for the benchmark table.
+ * Note: These are different from CheckIcon and CloseIcon in the design system because:
+ * - They have specific dimensions (16x16) required for the table
+ * - They use a different visual style that matches the benchmark UI
+ */
packages/web/docs/src/app/gateway/federation-compatible-benchmarks/benchmark-table-body.tsx (1)

42-46: Consider extracting styles to Tailwind classes.

The inline styles and TODO comment suggest a need for better style organization.

-                // todo: this is a bug in Components: we diverged from design
-                row.name === 'Hive Gateway' ? '!bg-green-100' : '',
-                'pl-5', // yes, the dot cuts in to the left per design
-                'max-sm:pr-1.5',
+                'pl-5 max-sm:pr-1.5',
+                row.name === 'Hive Gateway' && 'bg-green-100',
packages/web/docs/src/app/gateway/federation-compatible-benchmarks/index.tsx (2)

72-76: Add accessibility label to loading state.

The loading state should include an aria-label to improve accessibility.

-              <tbody aria-busy>
+              <tbody aria-busy aria-label="Loading benchmark data">

10-86: Add test coverage for the component.

Consider adding unit tests to verify:

  • Component renders correctly
  • Loading state is displayed while data is being fetched
  • Error boundary handles data loading failures appropriately

Would you like me to help create the test file with these test cases?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dac709f and 59ea959.

📒 Files selected for processing (6)
  • packages/web/docs/src/app/gateway/federation-compatible-benchmarks/benchmark-table-body.tsx (1 hunks)
  • packages/web/docs/src/app/gateway/federation-compatible-benchmarks/functional-tones.ts (1 hunks)
  • packages/web/docs/src/app/gateway/federation-compatible-benchmarks/icons.tsx (1 hunks)
  • packages/web/docs/src/app/gateway/federation-compatible-benchmarks/index.tsx (1 hunks)
  • packages/web/docs/src/app/gateway/page.tsx (2 hunks)
  • packages/web/docs/src/components/error-boundary.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`packages/web/docs/**`: The main landing page and documentat...

packages/web/docs/**: The main landing page and documentation website. It's built using TypeScript, Tailwind, NextJS and Nextra.

In PRs that adds a new feature to the product, we would like to make sure that the PR includes the following:

  • Up to date documentation in packages/web/docs/src/content
  • A product update in packages/web/docs/src/app/product-updates
  • packages/web/docs/src/app/gateway/federation-compatible-benchmarks/functional-tones.ts
  • packages/web/docs/src/app/gateway/page.tsx
  • packages/web/docs/src/app/gateway/federation-compatible-benchmarks/icons.tsx
  • packages/web/docs/src/components/error-boundary.ts
  • packages/web/docs/src/app/gateway/federation-compatible-benchmarks/benchmark-table-body.tsx
  • packages/web/docs/src/app/gateway/federation-compatible-benchmarks/index.tsx
🧠 Learnings (2)
packages/web/docs/src/app/gateway/federation-compatible-benchmarks/benchmark-table-body.tsx (1)
Learnt from: hasparus
PR: graphql-hive/console#6482
File: packages/web/docs/src/app/gateway/federation-compatible-benchmarks.tsx:188-204
Timestamp: 2025-02-06T16:15:18.151Z
Learning: When introducing new UI components, prefer keeping them close to their usage initially. Move components to the design system only when there's a clear need for reuse across multiple pages or websites, to avoid unnecessary version bumps and complexity.
packages/web/docs/src/app/gateway/federation-compatible-benchmarks/index.tsx (1)
Learnt from: hasparus
PR: graphql-hive/console#6482
File: packages/web/docs/src/app/gateway/federation-compatible-benchmarks.tsx:188-204
Timestamp: 2025-02-06T16:15:18.151Z
Learning: When introducing new UI components, prefer keeping them close to their usage initially. Move components to the design system only when there's a clear need for reuse across multiple pages or websites, to avoid unnecessary version bumps and complexity.
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: alpha / cli-test (macos-latest)
  • GitHub Check: build / dockerize (linux/arm64)
  • GitHub Check: build / dockerize (linux/amd64)
🔇 Additional comments (4)
packages/web/docs/src/app/gateway/page.tsx (2)

11-11: LGTM!

The imports are correctly organized and use appropriate relative paths.

Also applies to: 14-14


59-66: LGTM!

The ErrorBoundary implementation is well-placed and follows React best practices. The null fallback is appropriate as rendering the section without data would not be meaningful.

packages/web/docs/src/app/gateway/federation-compatible-benchmarks/index.tsx (2)

1-8: LGTM!

The imports are well-organized and the interface follows TypeScript best practices.


88-117: LGTM!

The BenchmarkLegend component is well-implemented with responsive design and consistent color usage.

Comment on lines +3 to +9
export function CheckmarkIcon(props: React.SVGProps<SVGSVGElement>) {
return (
<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor" {...props}>
<path d="M6.66668 10.1134L12.7947 3.98608L13.7373 4.92875L6.66668 11.9994L2.42401 7.75675L3.36668 6.81408L6.66668 10.1134Z" />
</svg>
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add ARIA labels for accessibility.

The icons should include ARIA labels for better accessibility.

 export function CheckmarkIcon(props: React.SVGProps<SVGSVGElement>) {
   return (
     <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor" 
+      aria-label="Success indicator"
+      role="img"
       {...props}>
       <path d="M6.66668 10.1134L12.7947 3.98608L13.7373 4.92875L6.66668 11.9994L2.42401 7.75675L3.36668 6.81408L6.66668 10.1134Z" />
     </svg>
   );
 }

 export function XIcon(props: React.SVGProps<SVGSVGElement>) {
   return (
     <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor"
+      aria-label="Failure indicator"
+      role="img"
       {...props}>
       <path d="M7.99999 7.05806L11.3 3.75806L12.2427 4.70072L8.94266 8.00072L12.2427 11.3007L11.2993 12.2434L7.99932 8.94339L4.69999 12.2434L3.75732 11.3001L7.05732 8.00006L3.75732 4.70006L4.69999 3.75872L7.99999 7.05806Z" />
     </svg>
   );
 }

Also applies to: 11-17

Comment on lines +64 to +79
<Table.Cell>
<span
className="inline-flex items-center gap-0.5 text-sm"
style={{ color: functionalTones.positiveDark }}
>
<CheckmarkIcon className="size-4" /> {row.cases.passed}
</span>
{row.cases.failed > 0 && (
<span
className="ml-2 inline-flex items-center text-sm"
style={{ color: functionalTones.criticalDark }}
>
<XIcon className="size-4" /> {row.cases.failed}
</span>
)}
</Table.Cell>
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Reduce code duplication in cell rendering.

The code for rendering passed/failed counts is duplicated between cases and suites cells.

+function MetricCell({ passed, failed }: { passed: number; failed: number }) {
+  return (
+    <Table.Cell>
+      <span
+        className="inline-flex items-center gap-0.5 text-sm"
+        style={{ color: functionalTones.positiveDark }}
+      >
+        <CheckmarkIcon className="size-4" /> {passed}
+      </span>
+      {failed > 0 && (
+        <span
+          className="ml-2 inline-flex items-center text-sm"
+          style={{ color: functionalTones.criticalDark }}
+        >
+          <XIcon className="size-4" /> {failed}
+        </span>
+      )}
+    </Table.Cell>
+  );
+}

// Then use it in the table:
-            <Table.Cell>
-              <span
-                className="inline-flex items-center gap-0.5 text-sm"
-                style={{ color: functionalTones.positiveDark }}
-              >
-                <CheckmarkIcon className="size-4" /> {row.cases.passed}
-              </span>
-              {row.cases.failed > 0 && (
-                <span
-                  className="ml-2 inline-flex items-center text-sm"
-                  style={{ color: functionalTones.criticalDark }}
-                >
-                  <XIcon className="size-4" /> {row.cases.failed}
-                </span>
-              )}
-            </Table.Cell>
+            <MetricCell passed={row.cases.passed} failed={row.cases.failed} />
-            <Table.Cell>
-              <span
-                className="inline-flex items-center gap-0.5 text-sm"
-                style={{ color: functionalTones.positiveDark }}
-              >
-                <CheckmarkIcon className="size-4" /> {row.suites.passed}
-              </span>
-              {row.suites.failed > 0 && (
-                <span
-                  className="ml-2 inline-flex items-center text-sm"
-                  style={{ color: functionalTones.criticalDark }}
-                >
-                  <XIcon className="size-4" /> {row.suites.failed}
-                </span>
-              )}
-            </Table.Cell>
+            <MetricCell passed={row.suites.passed} failed={row.suites.failed} />

Also applies to: 80-95

Comment on lines +20 to +26
const dataJson = fetch(
'https://the-guild.dev/graphql/hive/federation-gateway-audit/data.json',
).then(
res =>
// we didn't parse this, because we trust @kamilkisiela
res.json() as Promise<BenchmarkDatum[]>,
);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling for data fetching.

The data fetching logic should include proper error handling and loading states.

 const dataJson = fetch(
   'https://the-guild.dev/graphql/hive/federation-gateway-audit/data.json',
-).then(
-  res =>
-    // we didn't parse this, because we trust @kamilkisiela
-    res.json() as Promise<BenchmarkDatum[]>,
+).then(async res => {
+  if (!res.ok) {
+    throw new Error(`Failed to fetch benchmark data: ${res.status} ${res.statusText}`);
+  }
+  return res.json() as Promise<BenchmarkDatum[]>;
+});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const dataJson = fetch(
'https://the-guild.dev/graphql/hive/federation-gateway-audit/data.json',
).then(
res =>
// we didn't parse this, because we trust @kamilkisiela
res.json() as Promise<BenchmarkDatum[]>,
);
const dataJson = fetch(
'https://the-guild.dev/graphql/hive/federation-gateway-audit/data.json',
).then(async res => {
if (!res.ok) {
throw new Error(`Failed to fetch benchmark data: ${res.status} ${res.statusText}`);
}
return res.json() as Promise<BenchmarkDatum[]>;
});

return (
<tbody className="">
{data.map(row => {
const compatibility = (row.cases.passed / (row.cases.passed + row.cases.failed)) * 100;
Copy link
Contributor

@coderabbitai coderabbitai bot Feb 10, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add null check for compatibility calculation.

The compatibility calculation should handle the case where there are no test cases.

-        const compatibility = (row.cases.passed / (row.cases.passed + row.cases.failed)) * 100;
+        const totalCases = row.cases.passed + row.cases.failed;
+        const compatibility = totalCases > 0 ? (row.cases.passed / totalCases) * 100 : 0;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const compatibility = (row.cases.passed / (row.cases.passed + row.cases.failed)) * 100;
const totalCases = row.cases.passed + row.cases.failed;
const compatibility = totalCases > 0 ? (row.cases.passed / totalCases) * 100 : 0;

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

displaying wrong data here is worse than unmounting the component @coderabbitai

Copy link
Contributor

Choose a reason for hiding this comment

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

@hasparus You're absolutely right. I apologize for the suggestion. The ErrorBoundary approach you've implemented is better here, as it prevents displaying potentially misleading data.


✏️ Learnings added
Learnt from: hasparus
PR: graphql-hive/console#6482
File: packages/web/docs/src/app/gateway/federation-compatible-benchmarks/benchmark-table-body.tsx:36-36
Timestamp: 2025-02-10T19:27:30.330Z
Learning: For components displaying benchmark or performance data, prefer unmounting the component (e.g., using ErrorBoundary) over showing potentially incorrect data, as incorrect metrics can lead to wrong decisions.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@hasparus hasparus enabled auto-merge (squash) February 10, 2025 19:27
@kamilkisiela kamilkisiela merged commit 5307b0c into main Feb 11, 2025
29 of 30 checks passed
@kamilkisiela kamilkisiela deleted the hive-gateway-table branch February 11, 2025 10:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants