-
Notifications
You must be signed in to change notification settings - Fork 122
feat: restrict service creation by characters and length #6585
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
Conversation
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe update introduces a validation mechanism in the Changes
Possibly related PRs
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
🚀 Snapshot Release (
|
| Package | Version | Info |
|---|---|---|
@graphql-hive/cli |
0.49.1-alpha-20250310194937-2e46942a65c00cf49427a8c5efb97dc0c2b7306c |
npm ↗︎ unpkg ↗︎ |
hive |
5.1.4-alpha-20250310194937-2e46942a65c00cf49427a8c5efb97dc0c2b7306c |
npm ↗︎ unpkg ↗︎ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/services/api/src/modules/schema/providers/schema-publisher.ts (1)
1043-1058: Good implementation of service name validation requirements.The validation logic correctly checks that service names meet the specified criteria:
- Must be less than 64 characters
- Must start with a letter
- Can only contain alphanumeric characters, dash (-), or underscore (_)
Two minor observations about the regex:
- The global flag (
g) is unnecessary when usingtest()method as you're checking if the pattern matches the entire string\walready includes underscore, so there's a redundancy in[\w_-]where underscore is included twiceConsider this slight optimization to the regex:
-if (input.service.length > 64 || !/^[a-zA-Z][\w_-]+$/g.test(input.service)) { +if (input.service.length > 64 || !/^[a-zA-Z][\w-]+$/.test(input.service)) {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (1)
packages/services/api/src/modules/schema/providers/schema-publisher.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`packages/services/**`: Microservices written in NodeJS and ...
packages/services/**: Microservices written in NodeJS and TypeScript. Most of the dirs under this directory are packages and deployed as Docker packages.
Interaction between services is done using tRPC.
We prefer writing code that does input/output validations with Zod.
The directories that ends with-workerare projects that are built on top of CloudFlare Workers infrastructure and deployed there.
Thecdn-workeris a special one, it serves a high-available, detached CDN on CloudFlare Workers. This is how our end-users fetches the crucial data from our platform, in a way that does not depend/couple on our main API (served as GraphQL API).
packages/services/api/src/modules/schema/providers/schema-publisher.ts
⏰ Context from checks skipped due to timeout of 90000ms (9)
- GitHub Check: alpha / npm / snapshot
- 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: build / dockerize (linux/amd64)
- GitHub Check: alpha / cli-artifacts
- GitHub Check: code-style / eslint-and-prettier
|
🐋 This PR was built and pushed to the following Docker images: Targets: Platforms: Image Tag: 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": "2e46942a65c00cf49427a8c5efb97dc0c2b7306c",
"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": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:dockerfile": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:shared": "vwtvaockcxy2zg54vcsrvt112"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-cdcca3ba-965a-48b6-98a4-8f3451edc651/builder-cdcca3ba-965a-48b6-98a4-8f3451edc6510/0ob660i3wvgkn1ugnsmt1p3mu",
"containerimage.config.digest": "sha256:bf6a0800365d2901f8b5329fe7e3725683d23a9af8e19ed7a21a904dc5008d93",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:0c7db7c5f2c0d3a4d50982be3f908a95a3fb10437294c4d7abf6ea333f282594",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:0c7db7c5f2c0d3a4d50982be3f908a95a3fb10437294c4d7abf6ea333f282594",
"image.name": "ghcr.io/graphql-hive/app:2e46942a65c00cf49427a8c5efb97dc0c2b7306c-arm64,ghcr.io/graphql-hive/app:console_655-arm64"
},
"buildx.build.warnings": [
{
"vertex": "sha256:99e1536bf98a1cbabd377a5de48bd1482cb1f14779aac4403001d59a88ca1d44",
"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:85947d8057569c5f81df03af34cd059d0cb6abcb9040ffa14deb92b763f639af",
"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:85947d8057569c5f81df03af34cd059d0cb6abcb9040ffa14deb92b763f639af",
"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:85947d8057569c5f81df03af34cd059d0cb6abcb9040ffa14deb92b763f639af",
"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:85947d8057569c5f81df03af34cd059d0cb6abcb9040ffa14deb92b763f639af",
"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:99e1536bf98a1cbabd377a5de48bd1482cb1f14779aac4403001d59a88ca1d44",
"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:99e1536bf98a1cbabd377a5de48bd1482cb1f14779aac4403001d59a88ca1d44",
"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:99e1536bf98a1cbabd377a5de48bd1482cb1f14779aac4403001d59a88ca1d44",
"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
}
}
]
},
{
"vertex": "sha256:99e1536bf98a1cbabd377a5de48bd1482cb1f14779aac4403001d59a88ca1d44",
"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:99e1536bf98a1cbabd377a5de48bd1482cb1f14779aac4403001d59a88ca1d44",
"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:99e1536bf98a1cbabd377a5de48bd1482cb1f14779aac4403001d59a88ca1d44",
"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:99e1536bf98a1cbabd377a5de48bd1482cb1f14779aac4403001d59a88ca1d44",
"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:85947d8057569c5f81df03af34cd059d0cb6abcb9040ffa14deb92b763f639af",
"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:85947d8057569c5f81df03af34cd059d0cb6abcb9040ffa14deb92b763f639af",
"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
}
}
]
}
],
"commerce": {
"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 commerce service of the GraphQL Hive project.",
"build-arg:IMAGE_TITLE": "graphql-hive/commerce",
"build-arg:PORT": "3010",
"build-arg:RELEASE": "2e46942a65c00cf49427a8c5efb97dc0c2b7306c",
"build-arg:SERVICE_DIR_NAME": "@hive/commerce",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:dockerfile": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:shared": "vwtvaockcxy2zg54vcsrvt112"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-cdcca3ba-965a-48b6-98a4-8f3451edc651/builder-cdcca3ba-965a-48b6-98a4-8f3451edc6510/wmcxb0gfe27qwif2fkeyn4w73",
"containerimage.config.digest": "sha256:91587dfe8ab1f08b17f1d941198aaf5aa87621dc71e6e2898fa385a83a0a94ae",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:69bdd6e8eee99246aa21d1a545f26db5bab19203867c27671b2067938e4501b7",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:69bdd6e8eee99246aa21d1a545f26db5bab19203867c27671b2067938e4501b7",
"image.name": "ghcr.io/graphql-hive/commerce:2e46942a65c00cf49427a8c5efb97dc0c2b7306c-arm64,ghcr.io/graphql-hive/commerce:console_655-arm64"
},
"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": "2e46942a65c00cf49427a8c5efb97dc0c2b7306c",
"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": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:dockerfile": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:shared": "vwtvaockcxy2zg54vcsrvt112"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-cdcca3ba-965a-48b6-98a4-8f3451edc651/builder-cdcca3ba-965a-48b6-98a4-8f3451edc6510/jlznc1opxsm9a5e0it2zdgexd",
"containerimage.config.digest": "sha256:1b64b992a96da5ece0ef601bb9ab16a6f65fabeb57cef28d8d3e2fdffc18a89a",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:d2334767ab109ace1db6c77e7bc921180e484d1e70ee03b1011349d8ac971d3a",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:d2334767ab109ace1db6c77e7bc921180e484d1e70ee03b1011349d8ac971d3a",
"image.name": "ghcr.io/graphql-hive/composition-federation-2:2e46942a65c00cf49427a8c5efb97dc0c2b7306c-arm64,ghcr.io/graphql-hive/composition-federation-2:console_655-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": "2e46942a65c00cf49427a8c5efb97dc0c2b7306c",
"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": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:dockerfile": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:shared": "vwtvaockcxy2zg54vcsrvt112"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-cdcca3ba-965a-48b6-98a4-8f3451edc651/builder-cdcca3ba-965a-48b6-98a4-8f3451edc6510/47ma936rvdgzarhzzi0yz83d8",
"containerimage.config.digest": "sha256:cd25a5b13b65d591797a58b0e0b1f452f88bf26b09eceac3c7e97e5bf8be4d53",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:246764c363609d084a604176fa6c0dd20ced0d1a2ed297bcd5a4241653845223",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:246764c363609d084a604176fa6c0dd20ced0d1a2ed297bcd5a4241653845223",
"image.name": "ghcr.io/graphql-hive/emails:2e46942a65c00cf49427a8c5efb97dc0c2b7306c-arm64,ghcr.io/graphql-hive/emails:console_655-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": "2e46942a65c00cf49427a8c5efb97dc0c2b7306c",
"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": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:dockerfile": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:shared": "vwtvaockcxy2zg54vcsrvt112"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-cdcca3ba-965a-48b6-98a4-8f3451edc651/builder-cdcca3ba-965a-48b6-98a4-8f3451edc6510/rjlorsqgz5hnupy1pjqgwxfwq",
"containerimage.config.digest": "sha256:c7f557e6f710f0ae443c12366150c62504b82cf774112b3fb87d831a9c4e6583",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:820771d066d4d1916d10e84816a31a7f557f9ce01b80b1fc2d041383211772fc",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:820771d066d4d1916d10e84816a31a7f557f9ce01b80b1fc2d041383211772fc",
"image.name": "ghcr.io/graphql-hive/policy:2e46942a65c00cf49427a8c5efb97dc0c2b7306c-arm64,ghcr.io/graphql-hive/policy:console_655-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": "2e46942a65c00cf49427a8c5efb97dc0c2b7306c",
"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": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:dockerfile": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:shared": "vwtvaockcxy2zg54vcsrvt112"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-cdcca3ba-965a-48b6-98a4-8f3451edc651/builder-cdcca3ba-965a-48b6-98a4-8f3451edc6510/sa6an9cirtqs7rk6sycug81vw",
"containerimage.config.digest": "sha256:322fd01c60e1e58511f0f3ff5421af65d79b55b8a1379d1ae04c4439959ae40e",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:96f544f13b573576279779b44ad3b993e15f514083d42349a21f7512089b5476",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:96f544f13b573576279779b44ad3b993e15f514083d42349a21f7512089b5476",
"image.name": "ghcr.io/graphql-hive/schema:2e46942a65c00cf49427a8c5efb97dc0c2b7306c-arm64,ghcr.io/graphql-hive/schema:console_655-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": "2e46942a65c00cf49427a8c5efb97dc0c2b7306c",
"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": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:dockerfile": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:shared": "vwtvaockcxy2zg54vcsrvt112"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-cdcca3ba-965a-48b6-98a4-8f3451edc651/builder-cdcca3ba-965a-48b6-98a4-8f3451edc6510/btiayizoxtjq1gr924r4gdsaq",
"containerimage.config.digest": "sha256:0d83ae4eeb0c5c7073280d844c6376b721b91d7a6819bdf3d5c4b3c039a7fb3c",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:7ddb6b49c936801c35796889bdd4dfc71eb7bcab29bb901899b65941412dfc04",
"size": 2076,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:7ddb6b49c936801c35796889bdd4dfc71eb7bcab29bb901899b65941412dfc04",
"image.name": "ghcr.io/graphql-hive/server:2e46942a65c00cf49427a8c5efb97dc0c2b7306c-arm64,ghcr.io/graphql-hive/server:console_655-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": "2e46942a65c00cf49427a8c5efb97dc0c2b7306c",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:dockerfile": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:shared": "vwtvaockcxy2zg54vcsrvt112"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-cdcca3ba-965a-48b6-98a4-8f3451edc651/builder-cdcca3ba-965a-48b6-98a4-8f3451edc6510/vhc2zt8vmbbbhoi8jp4z41i64",
"containerimage.config.digest": "sha256:1471aa80d62c6735c4bc47b5407e425afcd9320217d6dac4bb311d3f70abcfdb",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:859cae0efabe1f6c39db4bb953a3bad632c592dda030cdf28edb97be87012035",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:859cae0efabe1f6c39db4bb953a3bad632c592dda030cdf28edb97be87012035",
"image.name": "ghcr.io/graphql-hive/storage:2e46942a65c00cf49427a8c5efb97dc0c2b7306c-arm64,ghcr.io/graphql-hive/storage:console_655-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": "2e46942a65c00cf49427a8c5efb97dc0c2b7306c",
"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": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:dockerfile": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:shared": "vwtvaockcxy2zg54vcsrvt112"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-cdcca3ba-965a-48b6-98a4-8f3451edc651/builder-cdcca3ba-965a-48b6-98a4-8f3451edc6510/m77l0ismxpltry2d3ut86hdqe",
"containerimage.config.digest": "sha256:85ff30abbf714e47e43a2065414f7161950310b8f05603ee5ce1f8447d6b478b",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:169694d56160eaaa57d3e92053c0b18f723ae4a9bd950fe3f5bb8001cdc67f17",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:169694d56160eaaa57d3e92053c0b18f723ae4a9bd950fe3f5bb8001cdc67f17",
"image.name": "ghcr.io/graphql-hive/tokens:2e46942a65c00cf49427a8c5efb97dc0c2b7306c-arm64,ghcr.io/graphql-hive/tokens:console_655-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": "2e46942a65c00cf49427a8c5efb97dc0c2b7306c",
"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": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:dockerfile": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:shared": "vwtvaockcxy2zg54vcsrvt112"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-cdcca3ba-965a-48b6-98a4-8f3451edc651/builder-cdcca3ba-965a-48b6-98a4-8f3451edc6510/jsdlyjw4ynbl4rvuzbrt7ufn3",
"containerimage.config.digest": "sha256:848d3e6e7da07fb5c8ab2cc9d1475a74e4c9881bc38d750a7b26b57446447661",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:967a4f4edfc20a4249e46ca28ae9b96f6b907fab2015c76e0abcce00bc4fb48e",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:967a4f4edfc20a4249e46ca28ae9b96f6b907fab2015c76e0abcce00bc4fb48e",
"image.name": "ghcr.io/graphql-hive/usage:2e46942a65c00cf49427a8c5efb97dc0c2b7306c-arm64,ghcr.io/graphql-hive/usage:console_655-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": "2e46942a65c00cf49427a8c5efb97dc0c2b7306c",
"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": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:dockerfile": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:shared": "vwtvaockcxy2zg54vcsrvt112"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-cdcca3ba-965a-48b6-98a4-8f3451edc651/builder-cdcca3ba-965a-48b6-98a4-8f3451edc6510/2sbk34t4d06m3zzn4t2mf82qx",
"containerimage.config.digest": "sha256:900b2ec2f52696a112d25335dfed37256b29f04624628d3e59ae30505a3572b0",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:16d358af4dadee4d484d81a3a0acbc15861ec795331e16a6e0b30ccdef49d61d",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:16d358af4dadee4d484d81a3a0acbc15861ec795331e16a6e0b30ccdef49d61d",
"image.name": "ghcr.io/graphql-hive/usage-ingestor:2e46942a65c00cf49427a8c5efb97dc0c2b7306c-arm64,ghcr.io/graphql-hive/usage-ingestor:console_655-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": "2e46942a65c00cf49427a8c5efb97dc0c2b7306c",
"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": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:dockerfile": "vwtvaockcxy2zg54vcsrvt112",
"local-sessionid:shared": "vwtvaockcxy2zg54vcsrvt112"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-cdcca3ba-965a-48b6-98a4-8f3451edc651/builder-cdcca3ba-965a-48b6-98a4-8f3451edc6510/mhi0ma3q2jnesm8pfyq5faef7",
"containerimage.config.digest": "sha256:3a86f3e62ce4327e68a1e218b8abebfe0a9c34c041a29e7c1277983bf11207e9",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:67f894ab918d3efbb013bcbe22678d81b8546782f70364dfbb791dfc477d1c84",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:67f894ab918d3efbb013bcbe22678d81b8546782f70364dfbb791dfc477d1c84",
"image.name": "ghcr.io/graphql-hive/webhooks:2e46942a65c00cf49427a8c5efb97dc0c2b7306c-arm64,ghcr.io/graphql-hive/webhooks:console_655-arm64"
}
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (3)
packages/services/api/src/modules/schema/providers/schema-publisher.ts (3)
1043-1058: Add Zod validation for service names to align with project standardsThe current implementation adds direct validation for service names which is good, but it could be improved by using Zod for consistency with other validations in the codebase. Also, there's a discrepancy between the regex and the error message - the regex allows forward slashes (
/) but the error message doesn't mention this.Consider refactoring this to use Zod validation for consistency, similar to the
SchemaCheckContextIdModelat the end of the file:- if (!latestVersion && input.service) { - // this is a new service. Validate the service name. - if (input.service.length > 64 || !/^[a-zA-Z][\w\/_-]*$/g.test(input.service)) { - return { - __typename: 'SchemaPublishError', - valid: false, - changes: [], - errors: [ - { - message: - 'Invalid service name. Service name must be less than 64 characters, must start with a letter, and can only contain alphanumeric characters, dash (-), or underscore (_).', - }, - ], - }; - } - } + if (!latestVersion && input.service) { + // this is a new service. Validate the service name. + const ServiceNameModel = z + .string() + .max(64, { + message: 'Service name must be less than 64 characters.', + }) + .regex(/^[a-zA-Z][\w_-]*$/, { + message: 'Service name must start with a letter and can only contain alphanumeric characters, dash (-), or underscore (_).', + }); + + const result = ServiceNameModel.safeParse(input.service); + if (!result.success) { + return { + __typename: 'SchemaPublishError', + valid: false, + changes: [], + errors: [ + { + message: `Invalid service name. ${result.error.errors[0].message}`, + }, + ], + }; + } + }Note that I've removed the forward slash (
/) from the regex and the global flag (g) as it's unnecessary for a pattern match test.
1045-1045: Remove the global flag from the regex patternThe global flag (
g) in the regex pattern is unnecessary when using thetest()method, as this method only checks if the pattern matches the string.- if (input.service.length > 64 || !/^[a-zA-Z][\w\/_-]*$/g.test(input.service)) { + if (input.service.length > 64 || !/^[a-zA-Z][\w\/_-]*$/.test(input.service)) {
1046-1056: Extract service name validation limits to constantsThe magic number "64" is hardcoded directly in the code. Consider extracting this and other validation rules to named constants for better maintainability and documentation.
Refactor the validation by adding constants at the class level or at the top of the file:
// Add at the top of the file or as class constants + const SERVICE_NAME_MAX_LENGTH = 64; + const SERVICE_NAME_PATTERN = /^[a-zA-Z][\w\/_-]*$/; // Then in the validation code - if (input.service.length > 64 || !/^[a-zA-Z][\w\/_-]*$/g.test(input.service)) { + if (input.service.length > SERVICE_NAME_MAX_LENGTH || !SERVICE_NAME_PATTERN.test(input.service)) { return { __typename: 'SchemaPublishError', valid: false, changes: [], errors: [ { message: - 'Invalid service name. Service name must be less than 64 characters, must start with a letter, and can only contain alphanumeric characters, dash (-), or underscore (_).', + `Invalid service name. Service name must be less than ${SERVICE_NAME_MAX_LENGTH} characters, must start with a letter, and can only contain alphanumeric characters, dash (-), or underscore (_).`, }, ], }; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/services/api/src/modules/schema/providers/schema-publisher.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`packages/services/**`: Microservices written in NodeJS and ...
packages/services/**: Microservices written in NodeJS and TypeScript. Most of the dirs under this directory are packages and deployed as Docker packages.
Interaction between services is done using tRPC.
We prefer writing code that does input/output validations with Zod.
The directories that ends with-workerare projects that are built on top of CloudFlare Workers infrastructure and deployed there.
Thecdn-workeris a special one, it serves a high-available, detached CDN on CloudFlare Workers. This is how our end-users fetches the crucial data from our platform, in a way that does not depend/couple on our main API (served as GraphQL API).
packages/services/api/src/modules/schema/providers/schema-publisher.ts
⏰ Context from checks skipped due to timeout of 90000ms (8)
- GitHub Check: alpha / npm / snapshot
- GitHub Check: static-analysis / analyze (typescript)
- GitHub Check: typescript / typecheck
- GitHub Check: static-analysis / analyze (javascript)
- GitHub Check: build / dockerize (linux/arm64)
- GitHub Check: code-style / eslint-and-prettier
- GitHub Check: build / dockerize (linux/amd64)
- GitHub Check: alpha / cli-artifacts
🔇 Additional comments (1)
packages/services/api/src/modules/schema/providers/schema-publisher.ts (1)
1043-1058:❓ Verification inconclusive
Verify validation implementation with existing services and automated tests
This PR adds validation for new service names only, which is a good approach to prevent disruption of existing services. Ensure thorough testing with various service name examples to confirm the validation works as expected.
🏁 Script executed:
#!/bin/bash # Find any existing tests that might need to be updated for the new validation # Search for tests related to SchemaPublisher.publish rg -A 10 "SchemaPublisher.*publish" --glob "*.test.ts" --glob "*.spec.ts" # Search for any examples of service name usage that might need validation rg -l "service_name" --glob "*.ts"Length of output: 1140
Ensure Comprehensive Test Coverage for New Service Name Validation
The new service name validation logic in
packages/services/api/src/modules/schema/providers/schema-publisher.ts(lines 1043-1058) is well-isolated to new services, which minimizes risk to existing functionality. However, please verify that the integration tests—particularly those inintegration-tests/tests/api/schema/publish.spec.ts—cover all edge cases. Confirm that tests include scenarios for service names that are too long, don't start with a letter, or include invalid characters, and ascertain that any modules referencing service names (as found in several files) remain consistent with this new validation.
packages/services/api/src/modules/schema/providers/schema-publisher.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
packages/services/api/src/modules/schema/providers/schema-publisher.ts (3)
1043-1058: The validation logic looks good, but there's a minor formatting issue in the error message.The service name validation logic is correctly implemented, checking both length and character requirements for new services. However, there's an extra comma in the error message that should be removed.
- 'Invalid service name. Service name must be less than 64 characters, must start with a letter, and can only contain alphanumeric characters, dash (-), underscore (_), , or forward slash (/).', + 'Invalid service name. Service name must be less than 64 characters, must start with a letter, and can only contain alphanumeric characters, dash (-), underscore (_), or forward slash (/).',
1045-1045: Optimize the regex pattern by removing redundancy.The current regex has redundant parts that can be simplified without changing its behavior.
- if (input.service.length > 64 || !/^[a-zA-Z][\w\/_-]*$/g.test(input.service)) { + if (input.service.length > 64 || !/^[a-zA-Z][\w\/-]*$/g.test(input.service)) {The
_in the character class is redundant since\walready includes underscores (it matches[a-zA-Z0-9_]). Also, the global flag (g) is unnecessary for a single validation test.
1045-1057: Consider optimizing the validation logic for better performance and clearer error messages.For better user experience and performance, consider separating the validation checks and providing more specific error messages for each case.
- if (input.service.length > 64 || !/^[a-zA-Z][\w\/_-]*$/g.test(input.service)) { - return { - __typename: 'SchemaPublishError', - valid: false, - changes: [], - errors: [ - { - message: - 'Invalid service name. Service name must be less than 64 characters, must start with a letter, and can only contain alphanumeric characters, dash (-), underscore (_), , or forward slash (/).', - }, - ], - }; - } + // Check length first + if (input.service.length > 64) { + return { + __typename: 'SchemaPublishError', + valid: false, + changes: [], + errors: [ + { + message: 'Service name is too long. Maximum length is 64 characters.', + }, + ], + }; + } + + // Then check character constraints + if (!/^[a-zA-Z][\w\/-]*$/.test(input.service)) { + return { + __typename: 'SchemaPublishError', + valid: false, + changes: [], + errors: [ + { + message: 'Invalid service name. Service name must start with a letter and can only contain alphanumeric characters, dash (-), underscore (_), or forward slash (/).', + }, + ], + }; + }This approach has several benefits:
- Better performance - avoids running regex on long strings that will fail the length check anyway
- More specific error messages help users understand exactly what's wrong
- Simplified regex without redundant parts
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/services/api/src/modules/schema/providers/schema-publisher.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`packages/services/**`: Microservices written in NodeJS and ...
packages/services/**: Microservices written in NodeJS and TypeScript. Most of the dirs under this directory are packages and deployed as Docker packages.
Interaction between services is done using tRPC.
We prefer writing code that does input/output validations with Zod.
The directories that ends with-workerare projects that are built on top of CloudFlare Workers infrastructure and deployed there.
Thecdn-workeris a special one, it serves a high-available, detached CDN on CloudFlare Workers. This is how our end-users fetches the crucial data from our platform, in a way that does not depend/couple on our main API (served as GraphQL API).
packages/services/api/src/modules/schema/providers/schema-publisher.ts
⏰ Context from checks skipped due to timeout of 90000ms (9)
- GitHub Check: alpha / npm / snapshot
- 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: build / dockerize (linux/amd64)
- GitHub Check: code-style / eslint-and-prettier
- GitHub Check: alpha / cli-artifacts
🔇 Additional comments (2)
packages/services/api/src/modules/schema/providers/schema-publisher.ts (2)
1045-1045: Fix inconsistency between regex and error message regarding allowed charactersThe regex pattern allows forward slashes (
/), but the error message doesn't mention this. This creates an inconsistency between what's allowed and what's communicated to the user.
1043-1058:❓ Verification inconclusive
Verify behavior with existing service names in the system.
The validation is only applied for new services (
!latestVersion && input.service), which aligns with the PR objective of not disrupting existing services. Consider creating a migration plan for legacy services that don't meet these criteria.
🏁 Script executed:
#!/bin/bash # Description: Find any existing service names that wouldn't pass the new validation rules # Search for service_name fields in the codebase echo "Checking for service name patterns in the codebase..." # First search for service names with invalid characters rg "service_name['\"]?\s*[=:]\s*['\"]([^a-zA-Z]|[^a-zA-Z0-9_\/-])" --type ts # Then search for potentially long service names (look for strings with 50+ chars that might be service names) echo "Checking for potentially long service names..." rg "service_name['\"]?\s*[=:]\s*['\"][a-zA-Z][a-zA-Z0-9_\/-]{49,}" --type tsLength of output: 741
Action Required: Verify Legacy Service Name Behavior & Fix Regex in Verification Script
- The new validation correctly checks new services (
!latestVersion && input.service) without disrupting existing services, aligning with the intent.- However, the verification script encountered regex parse errors (unrecognized escape sequences). Please update the regex patterns to match your engine's syntax—for example, adjusting escape sequences or quoting—to accurately search for existing service names.
- Additionally, consider manually verifying any legacy service names that might not comply with the new naming criteria and prepare a migration plan for them if required.
| this.schemaManager.getMaybeLatestVersion(target), | ||
| ]); | ||
|
|
||
| if (!latestVersion && input.service) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we would rather have to check whether the latestVersion has a service associated named like this service? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There would also be an edge case, where someone deletes a service (hive schema:delete) and tries to republish it, but then it fails, because it would no longer be in the previous version 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Youre right about the latestVersion. I'll fix that.
For the edge case, I think we can ignore that. If they are deleting then we can treat like new.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added validation to schema check also. This will prevent us from having issues where the check passes but push fails because of the service name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
packages/services/api/src/modules/schema/providers/schema-helper.ts(1 hunks)packages/services/api/src/modules/schema/providers/schema-publisher.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`packages/services/**`: Microservices written in NodeJS and ...
packages/services/**: Microservices written in NodeJS and TypeScript. Most of the dirs under this directory are packages and deployed as Docker packages.
Interaction between services is done using tRPC.
We prefer writing code that does input/output validations with Zod.
The directories that ends with-workerare projects that are built on top of CloudFlare Workers infrastructure and deployed there.
Thecdn-workeris a special one, it serves a high-available, detached CDN on CloudFlare Workers. This is how our end-users fetches the crucial data from our platform, in a way that does not depend/couple on our main API (served as GraphQL API).
packages/services/api/src/modules/schema/providers/schema-publisher.tspackages/services/api/src/modules/schema/providers/schema-helper.ts
🔇 Additional comments (1)
packages/services/api/src/modules/schema/providers/schema-helper.ts (1)
40-42: Improved type signature for ensureCompositeSchemasRemoving the
| neverfrom the return type is a good change. The function now correctly indicates it returns an array ofCompositeSchemaobjects, which is more accurate since the function doesn't actually throw any exceptions (it just filters the input array).
| throw new Error('Expected a single schema'); | ||
| } | ||
|
|
||
| export function ensureCompositeSchemas(schemas: readonly Schema[]): CompositeSchema[] | never { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assumed this never was because the function threw an array, but it only filters. So I'm not sure why this never is here... removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
packages/services/api/src/modules/schema/providers/schema-publisher.ts (3)
331-353: Consider unifying repeated validation logic for new services.
The validation for a new service name here is almost identical to the subsequent block in the publish method. Extracting this logic to a shared function (beyondisValidServiceName) or unifying checks may reduce duplication and improve maintainability.
1077-1099: Again, consider consolidating duplicate checks for new service name validation.
Similar to the earlier block for schema checks, you can refactor these lines to avoid duplication of the same checks and error messaging in multiple locations.
2497-2500: Remove unnecessary regex “g” flag.
Since you are doing a single pass test of the entire string, you don’t need thegflag here.-function isValidServiceName(service: string): boolean { - return service.length <= 64 && /^[a-zA-Z][\w\/_-]*$/g.test(service); +function isValidServiceName(service: string): boolean { + return service.length <= 64 && /^[a-zA-Z][\w\/_-]*$/.test(service); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/services/api/src/modules/schema/providers/schema-publisher.ts(3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`packages/services/**`: Microservices written in NodeJS and ...
packages/services/**: Microservices written in NodeJS and TypeScript. Most of the dirs under this directory are packages and deployed as Docker packages.
Interaction between services is done using tRPC.
We prefer writing code that does input/output validations with Zod.
The directories that ends with-workerare projects that are built on top of CloudFlare Workers infrastructure and deployed there.
Thecdn-workeris a special one, it serves a high-available, detached CDN on CloudFlare Workers. This is how our end-users fetches the crucial data from our platform, in a way that does not depend/couple on our main API (served as GraphQL API).
packages/services/api/src/modules/schema/providers/schema-publisher.ts
⏰ Context from checks skipped due to timeout of 90000ms (9)
- GitHub Check: alpha / npm / snapshot
- 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: build / dockerize (linux/amd64)
- GitHub Check: code-style / eslint-and-prettier
- GitHub Check: alpha / cli-artifacts
🔇 Additional comments (1)
packages/services/api/src/modules/schema/providers/schema-publisher.ts (1)
1064-1075: Conditional fetch optimization looks good.
Fetching the latest schemas only wheninput.serviceis provided helps avoid unnecessary database calls for single-service workflows.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
.changeset/rotten-scissors-matter.md (2)
6-6: Descriptive Text Clarity:
The description clearly states the new restriction for service names (limited to 64 characters and restricted to alphanumeric characters, underscores, hyphens, and slashes). However, there is a minor typographical error: "alphanumberic" should be "alphanumeric" to maintain clarity and professionalism.
7-7: Stray Content Identified:
Line 7 contains an isolated "7" which appears to be unintentional. If this is not a deliberate part of the changeset description, consider removing it to avoid confusion.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.changeset/rotten-scissors-matter.md(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`.changeset/**`: A special folder with the files created/man...
.changeset/**: A special folder with the files created/managed by Changesets tool.
In PRs that already includes this file, please make sure that the content of the markdown file includes:
- Full description of the change
- A link to the relevant GitHub issues (if any)
- Example with before/after
- If the change is of type
major, please ensure that the content have content about migration with before/after.
.changeset/rotten-scissors-matter.md
⏰ Context from checks skipped due to timeout of 90000ms (9)
- GitHub Check: alpha / npm / snapshot
- GitHub Check: test / unit
- GitHub Check: typescript / typecheck
- GitHub Check: static-analysis / analyze (typescript)
- GitHub Check: static-analysis / analyze (javascript)
- GitHub Check: code-style / eslint-and-prettier
- GitHub Check: build / dockerize (linux/arm64)
- GitHub Check: build / dockerize (linux/amd64)
- GitHub Check: alpha / cli-artifacts
🔇 Additional comments (1)
.changeset/rotten-scissors-matter.md (1)
1-4: YAML Front Matter Integrity:
The YAML front matter is correctly structured and specifies patch releases for both'hive'and'@graphql-hive/cli'. Ensure that these package changes align with your release process.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets add integration tests for this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
packages/services/api/src/modules/schema/providers/schema-publisher.ts (3)
2520-2522: Optimize the service name validation regexThe regex pattern could be improved for better readability and efficiency:
\walready includes alphanumeric characters and underscore, so including_separately is redundant- The global flag
gis unnecessary for a single test- Consider adding JSDoc comments to document this function's purpose and parameters
+/** + * Validates a service name against the following criteria: + * - Must be 64 characters or less + * - Must start with a letter + * - Can only contain alphanumeric characters, dash (-), underscore (_), or forward slash (/) + * @param service The service name to validate + * @returns boolean indicating if the service name is valid + */ function isValidServiceName(service: string): boolean { - return service.length <= 64 && /^[a-zA-Z][\w\/_-]*$/g.test(service); + return service.length <= 64 && /^[a-zA-Z][\w\/-]*$/.test(service); }
331-353: Consider extracting the error message to avoid duplicationThe error message text for invalid service names is duplicated between the
internalCheckandpublishmethods, which could lead to inconsistencies if one is updated but not the other.Extract the error message to a constant at the file level:
+const INVALID_SERVICE_NAME_ERROR = 'Invalid service name. Service name must be 64 characters or less, must start with a letter, and can only contain alphanumeric characters, dash (-), underscore (_), or forward slash (/).'; // Then in this function if (!serviceExists && !isValidServiceName(input.service)) { return { __typename: 'SchemaCheckError', valid: false, changes: [], warnings: [], errors: [ { message: - 'Invalid service name. Service name must be 64 characters or less, must start with a letter, and can only contain alphanumeric characters, dash (-), underscore (_), or forward slash (/).', + INVALID_SERVICE_NAME_ERROR, }, ], } as const; }
1085-1096: Improve readability of conditional Promise resolutionThe conditional Promise.resolve() could be made clearer by using a ternary operator to make the intent more explicit.
const [contracts, latestVersion, latestSchemas] = await Promise.all([ this.contracts.getActiveContractsByTargetId({ targetId: selector.targetId }), this.schemaManager.getMaybeLatestVersion(target), - input.service - ? this.storage.getLatestSchemas({ - organizationId: selector.organizationId, - projectId: selector.projectId, - targetId: selector.targetId, - }) - : Promise.resolve(), + input.service ? this.storage.getLatestSchemas({ + organizationId: selector.organizationId, + projectId: selector.projectId, + targetId: selector.targetId, + }) : Promise.resolve(undefined), ]);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/services/api/src/modules/schema/providers/schema-publisher.ts(3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`packages/services/**`: Microservices written in NodeJS and ...
packages/services/**: Microservices written in NodeJS and TypeScript. Most of the dirs under this directory are packages and deployed as Docker packages.
Interaction between services is done using tRPC.
We prefer writing code that does input/output validations with Zod.
The directories that ends with-workerare projects that are built on top of CloudFlare Workers infrastructure and deployed there.
Thecdn-workeris a special one, it serves a high-available, detached CDN on CloudFlare Workers. This is how our end-users fetches the crucial data from our platform, in a way that does not depend/couple on our main API (served as GraphQL API).
packages/services/api/src/modules/schema/providers/schema-publisher.ts
⏰ Context from checks skipped due to timeout of 90000ms (9)
- GitHub Check: alpha / npm / snapshot
- GitHub Check: alpha / cli-artifacts
- GitHub Check: typescript / typecheck
- GitHub Check: static-analysis / analyze (typescript)
- GitHub Check: static-analysis / analyze (javascript)
- GitHub Check: code-style / eslint-and-prettier
- GitHub Check: test / unit
- GitHub Check: build / dockerize (linux/arm64)
- GitHub Check: build / dockerize (linux/amd64)
🔇 Additional comments (1)
packages/services/api/src/modules/schema/providers/schema-publisher.ts (1)
1098-1120: Use the extracted error message constant here as wellThis is the second occurrence of the same error message text. Using the same constant here would ensure consistency.
if (!serviceExists && !isValidServiceName(input.service)) { return { __typename: 'SchemaPublishError', valid: false, changes: [], errors: [ { message: - 'Invalid service name. Service name must be 64 characters or less, must start with a letter, and can only contain alphanumeric characters, dash (-), underscore (_), or forward slash (/).', + INVALID_SERVICE_NAME_ERROR, }, ], }; }
|
I am not sure whether we want to allow My main argument for this is that our resource identifiers use the Examples: I think it is very unlikely that service name or app deployment will have a "sub" resource e.g. But if we would introduce something like this, it would require additional adjustments if the Thoughts? |
|
That makes sense to me. It seems like best practices to keep the character list to a minimum also to avoid edge cases such as this. So I'll adjust that. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
integration-tests/tests/cli/schema.spec.ts (2)
98-151: Well-structured test for service name validation in publishingThis test comprehensively validates the service name restrictions when publishing a schema. The test appropriately:
- Skips for single project types where service names aren't applicable
- Tests rejection of numeric-only names
- Tests rejection of names with special characters
- Verifies acceptance of valid names with alphanumeric characters and hyphens
However, based on the PR objectives, there was discussion about not allowing the
/character specifically. Consider adding an explicit test case for a service name containing the/character to ensure it's properly rejected.await expect( schemaPublish([ '--registry.accessToken', secret, '--author', 'Kamil', '--commit', 'abc123', '--service', 'asdf$#%^#@!#', ...serviceUrlArgs, 'fixtures/init-schema.graphql', ]), ).rejects.toMatchSnapshot('specialCharacters'); + // Test rejection of service name with slash character specifically + await expect( + schemaPublish([ + '--registry.accessToken', + secret, + '--author', + 'Kamil', + '--commit', + 'abc123', + '--service', + 'invalid/name', + ...serviceUrlArgs, + 'fixtures/init-schema.graphql', + ]), + ).rejects.toMatchSnapshot('nameWithSlash'); +
153-203: Consistent validation test for schema checking operationThis test properly mirrors the publishing test to ensure consistent validation behavior when checking schemas. The test cases comprehensively cover numeric-only names, names with special characters, and valid names.
Similar to the previous test, consider adding a specific test case for a service name containing the
/character to address the explicit concern raised in the PR objectives discussion.await expect( schemaCheck([ '--registry.accessToken', secret, '--author', 'Kamil', '--commit', 'abc123', '--service', 'asdf$#%^#@!#', 'fixtures/init-schema.graphql', ]), ).rejects.toMatchSnapshot('specialCharacters'); + // Test rejection of service name with slash character specifically + await expect( + schemaCheck([ + '--registry.accessToken', + secret, + '--author', + 'Kamil', + '--commit', + 'abc123', + '--service', + 'invalid/name', + 'fixtures/init-schema.graphql', + ]), + ).rejects.toMatchSnapshot('nameWithSlash'); +
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
integration-tests/tests/cli/schema.spec.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`integration-tests/**`: integration tests for ensuring featu...
integration-tests/**: integration tests for ensuring features and important flows are running. Usually, changes to thepackages/directory will affect this. In ideal flow, each PR should include integration tests.
integration-tests/tests/cli/schema.spec.ts
⏰ Context from checks skipped due to timeout of 90000ms (9)
- GitHub Check: alpha / npm / snapshot
- GitHub Check: typescript / typecheck
- GitHub Check: test / unit
- GitHub Check: static-analysis / analyze (typescript)
- GitHub Check: static-analysis / analyze (javascript)
- GitHub Check: build / dockerize (linux/arm64)
- GitHub Check: build / dockerize (linux/amd64)
- GitHub Check: alpha / cli-artifacts
- GitHub Check: code-style / eslint-and-prettier
n1ru4l
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice 🥳
Background
Closes #6423
Description
Ideally this validation should exist on the model but if we did that, we'd start rejecting services that already exist.
This is at least a start to restricting services to better names.
Modifying documentation to mention this new restriction will come as a followup PR.
Checklist