-
Notifications
You must be signed in to change notification settings - Fork 106
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
improve(laboratory): validate editor content with TypeScript #6476
base: main
Are you sure you want to change the base?
Conversation
Draft because there are no tests yet. |
📚 Storybook DeploymentThe latest changes are available as preview in: https://039f4fc2.hive-storybook.pages.dev |
🐋 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": "ebe9be3990d1597cbe8fe62869d9a000f1ac751f",
"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": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:dockerfile": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:shared": "nqqyrvjz465mpn6ocxkgpb1mu"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-5b941d15-1932-4436-bc2b-bd94ca461f03/builder-5b941d15-1932-4436-bc2b-bd94ca461f030/ro66433ngj95t5xi7bzu0ts3b",
"containerimage.config.digest": "sha256:d2bcb3ddfd79aa0c79ec70b403633e6cd104869bbd4557c8ba93ff3592166db4",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:210d16afffa66988a00b6fe70ed0c02a13701fd6e921d5a37574bb76fcc72a7f",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:210d16afffa66988a00b6fe70ed0c02a13701fd6e921d5a37574bb76fcc72a7f",
"image.name": "ghcr.io/graphql-hive/app:ebe9be3990d1597cbe8fe62869d9a000f1ac751f-arm64,ghcr.io/graphql-hive/app:console_1003-arm64"
},
"buildx.build.warnings": [
{
"vertex": "sha256:3c5087129863cca940b0056dbb435f61c5bb863b47557c5fa5a66269e337a9b1",
"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:3c5087129863cca940b0056dbb435f61c5bb863b47557c5fa5a66269e337a9b1",
"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:3c5087129863cca940b0056dbb435f61c5bb863b47557c5fa5a66269e337a9b1",
"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:57248d07ea1e3bf6065526c28942441717372a5dfc14c736cb22a7bae6ce3fb6",
"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:3c5087129863cca940b0056dbb435f61c5bb863b47557c5fa5a66269e337a9b1",
"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:57248d07ea1e3bf6065526c28942441717372a5dfc14c736cb22a7bae6ce3fb6",
"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:57248d07ea1e3bf6065526c28942441717372a5dfc14c736cb22a7bae6ce3fb6",
"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:57248d07ea1e3bf6065526c28942441717372a5dfc14c736cb22a7bae6ce3fb6",
"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:3c5087129863cca940b0056dbb435f61c5bb863b47557c5fa5a66269e337a9b1",
"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:3c5087129863cca940b0056dbb435f61c5bb863b47557c5fa5a66269e337a9b1",
"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:3c5087129863cca940b0056dbb435f61c5bb863b47557c5fa5a66269e337a9b1",
"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:57248d07ea1e3bf6065526c28942441717372a5dfc14c736cb22a7bae6ce3fb6",
"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:3c5087129863cca940b0056dbb435f61c5bb863b47557c5fa5a66269e337a9b1",
"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:57248d07ea1e3bf6065526c28942441717372a5dfc14c736cb22a7bae6ce3fb6",
"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
}
}
]
}
],
"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": "ebe9be3990d1597cbe8fe62869d9a000f1ac751f",
"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": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:dockerfile": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:shared": "nqqyrvjz465mpn6ocxkgpb1mu"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-5b941d15-1932-4436-bc2b-bd94ca461f03/builder-5b941d15-1932-4436-bc2b-bd94ca461f030/2b5i8iom0iqsl0draa3njsy7c",
"containerimage.config.digest": "sha256:198eda3f253e9c4df078e344b01737e9e6b8bf0b5db6652d523a998aba87f580",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:d8c88fe12dddacfe920d725ec21d37df157b9b7102572ddde4c5a5ec067f2e31",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:d8c88fe12dddacfe920d725ec21d37df157b9b7102572ddde4c5a5ec067f2e31",
"image.name": "ghcr.io/graphql-hive/composition-federation-2:ebe9be3990d1597cbe8fe62869d9a000f1ac751f-arm64,ghcr.io/graphql-hive/composition-federation-2:console_1003-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": "ebe9be3990d1597cbe8fe62869d9a000f1ac751f",
"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": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:dockerfile": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:shared": "nqqyrvjz465mpn6ocxkgpb1mu"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-5b941d15-1932-4436-bc2b-bd94ca461f03/builder-5b941d15-1932-4436-bc2b-bd94ca461f030/efj6b5izxdmjkhicgkk1rez1r",
"containerimage.config.digest": "sha256:28783635b253ba9d1dccba7a62ecdefc742fd42d1380cf005fdf253cf92281b1",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:b529090b1f1f8038014063dea094f25b37f34352589d26fba2e3f2703d2bead5",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:b529090b1f1f8038014063dea094f25b37f34352589d26fba2e3f2703d2bead5",
"image.name": "ghcr.io/graphql-hive/emails:ebe9be3990d1597cbe8fe62869d9a000f1ac751f-arm64,ghcr.io/graphql-hive/emails:console_1003-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": "ebe9be3990d1597cbe8fe62869d9a000f1ac751f",
"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": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:dockerfile": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:shared": "nqqyrvjz465mpn6ocxkgpb1mu"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-5b941d15-1932-4436-bc2b-bd94ca461f03/builder-5b941d15-1932-4436-bc2b-bd94ca461f030/kxlfmejqu9e4al6sp6xzuv41p",
"containerimage.config.digest": "sha256:ba1cc7a70f13836ae683a76a98aab562076ac7173ac2681cad86b5f46eede0fd",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:e3618cdd0ce9087d08497ac3076fd5117beaa07efbc7e31c8e739e4ba20d89b6",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:e3618cdd0ce9087d08497ac3076fd5117beaa07efbc7e31c8e739e4ba20d89b6",
"image.name": "ghcr.io/graphql-hive/policy:ebe9be3990d1597cbe8fe62869d9a000f1ac751f-arm64,ghcr.io/graphql-hive/policy:console_1003-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": "ebe9be3990d1597cbe8fe62869d9a000f1ac751f",
"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": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:dockerfile": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:shared": "nqqyrvjz465mpn6ocxkgpb1mu"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-5b941d15-1932-4436-bc2b-bd94ca461f03/builder-5b941d15-1932-4436-bc2b-bd94ca461f030/tf9o4pow7p2nuwvw1861oqjv0",
"containerimage.config.digest": "sha256:7b3d9f0f562a27b7d21221b843ac7206b937ff6936cdf4fed90613f5ab175d41",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:c2ec197585b48745e291b06096cb9d199e4f6487d897daa0842a5201090e70e6",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:c2ec197585b48745e291b06096cb9d199e4f6487d897daa0842a5201090e70e6",
"image.name": "ghcr.io/graphql-hive/rate-limit:ebe9be3990d1597cbe8fe62869d9a000f1ac751f-arm64,ghcr.io/graphql-hive/rate-limit:console_1003-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": "ebe9be3990d1597cbe8fe62869d9a000f1ac751f",
"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": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:dockerfile": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:shared": "nqqyrvjz465mpn6ocxkgpb1mu"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-5b941d15-1932-4436-bc2b-bd94ca461f03/builder-5b941d15-1932-4436-bc2b-bd94ca461f030/9ewnzhzax41hn0vaq0bs130w1",
"containerimage.config.digest": "sha256:6a8ddc598ff3ce3bf3c3da672a823e85b2763ab03d22fb9df86fb3bb80a18391",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:149451aeac3ca971c93724bceb0081f7d1f70dcffffb293227e207a905a30867",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:149451aeac3ca971c93724bceb0081f7d1f70dcffffb293227e207a905a30867",
"image.name": "ghcr.io/graphql-hive/schema:ebe9be3990d1597cbe8fe62869d9a000f1ac751f-arm64,ghcr.io/graphql-hive/schema:console_1003-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": "ebe9be3990d1597cbe8fe62869d9a000f1ac751f",
"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": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:dockerfile": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:shared": "nqqyrvjz465mpn6ocxkgpb1mu"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-5b941d15-1932-4436-bc2b-bd94ca461f03/builder-5b941d15-1932-4436-bc2b-bd94ca461f030/jzkoyphf06aq606s0j5w106kf",
"containerimage.config.digest": "sha256:2d0f815ff3770afe798d34a0a3f5df2188febcc072f28f3d1ee9dd9d924682fb",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:454cf5eae21f2e279e011bf237ea64a4bacb937b3677303fcf6c666946b15a58",
"size": 2076,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:454cf5eae21f2e279e011bf237ea64a4bacb937b3677303fcf6c666946b15a58",
"image.name": "ghcr.io/graphql-hive/server:ebe9be3990d1597cbe8fe62869d9a000f1ac751f-arm64,ghcr.io/graphql-hive/server:console_1003-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": "ebe9be3990d1597cbe8fe62869d9a000f1ac751f",
"context:dist": "local:dist",
"context:shared": "local:shared",
"frontend.caps": "moby.buildkit.frontend.contexts+forward",
"local-sessionid:context": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:dockerfile": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:shared": "nqqyrvjz465mpn6ocxkgpb1mu"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-5b941d15-1932-4436-bc2b-bd94ca461f03/builder-5b941d15-1932-4436-bc2b-bd94ca461f030/hzceqiepa0rakqcvodbyhr55j",
"containerimage.config.digest": "sha256:f3b23b21edcdfbc535b6f0e126c401042a989aaee0509494627719cc5654513d",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:6507bcd83ed043b4ca847aceaf2006b0f0f22fb13d26debb482b890171fe38d2",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:6507bcd83ed043b4ca847aceaf2006b0f0f22fb13d26debb482b890171fe38d2",
"image.name": "ghcr.io/graphql-hive/storage:ebe9be3990d1597cbe8fe62869d9a000f1ac751f-arm64,ghcr.io/graphql-hive/storage:console_1003-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": "ebe9be3990d1597cbe8fe62869d9a000f1ac751f",
"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": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:dockerfile": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:shared": "nqqyrvjz465mpn6ocxkgpb1mu"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-5b941d15-1932-4436-bc2b-bd94ca461f03/builder-5b941d15-1932-4436-bc2b-bd94ca461f030/o268lzu2xgogumd9w7nm0a7ia",
"containerimage.config.digest": "sha256:b66aa5cde8d6d2e38a2bc20721c07eb1294ddb5ea2365f5338afa8f5828d40b2",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:3c0e621394c008b973a3f3a541453fc7055887fff34b180dad6ee6d81b1e6001",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:3c0e621394c008b973a3f3a541453fc7055887fff34b180dad6ee6d81b1e6001",
"image.name": "ghcr.io/graphql-hive/stripe-billing:ebe9be3990d1597cbe8fe62869d9a000f1ac751f-arm64,ghcr.io/graphql-hive/stripe-billing:console_1003-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": "ebe9be3990d1597cbe8fe62869d9a000f1ac751f",
"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": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:dockerfile": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:shared": "nqqyrvjz465mpn6ocxkgpb1mu"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-5b941d15-1932-4436-bc2b-bd94ca461f03/builder-5b941d15-1932-4436-bc2b-bd94ca461f030/elkuzrnbzox6sey1k6no8nzz5",
"containerimage.config.digest": "sha256:114d91e955bde2cb9993d6cdb0d4006f9bafa5da1491abe5c80bd77ac8b6b1b0",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:13b68676cab5896f796735702ac22f8105783c8707276d67c29b543a9f6809e6",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:13b68676cab5896f796735702ac22f8105783c8707276d67c29b543a9f6809e6",
"image.name": "ghcr.io/graphql-hive/tokens:ebe9be3990d1597cbe8fe62869d9a000f1ac751f-arm64,ghcr.io/graphql-hive/tokens:console_1003-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": "ebe9be3990d1597cbe8fe62869d9a000f1ac751f",
"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": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:dockerfile": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:shared": "nqqyrvjz465mpn6ocxkgpb1mu"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-5b941d15-1932-4436-bc2b-bd94ca461f03/builder-5b941d15-1932-4436-bc2b-bd94ca461f030/n1d6hpfpjk8562i3504hkh3k3",
"containerimage.config.digest": "sha256:a8d8c57227084c90a444910a17dfcd8bfb9f1fbf6257056452cf20fa45e18469",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:b68d155917bca424b977966f0513ad6d439a365704836fdc623018f31ed393e8",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:b68d155917bca424b977966f0513ad6d439a365704836fdc623018f31ed393e8",
"image.name": "ghcr.io/graphql-hive/usage:ebe9be3990d1597cbe8fe62869d9a000f1ac751f-arm64,ghcr.io/graphql-hive/usage:console_1003-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": "ebe9be3990d1597cbe8fe62869d9a000f1ac751f",
"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": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:dockerfile": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:shared": "nqqyrvjz465mpn6ocxkgpb1mu"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-5b941d15-1932-4436-bc2b-bd94ca461f03/builder-5b941d15-1932-4436-bc2b-bd94ca461f030/a2hgammjnpi4igitixk42ps1o",
"containerimage.config.digest": "sha256:da2969ae7ac08c0910b56811d0d2a4965d79cb017a6c193296a3c8c2bd13a8f4",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:0dad703d35c2c10b0ec5be9ab1cf11923e59dae52e98f354c050a67c2b04ccea",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:0dad703d35c2c10b0ec5be9ab1cf11923e59dae52e98f354c050a67c2b04ccea",
"image.name": "ghcr.io/graphql-hive/usage-estimator:ebe9be3990d1597cbe8fe62869d9a000f1ac751f-arm64,ghcr.io/graphql-hive/usage-estimator:console_1003-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": "ebe9be3990d1597cbe8fe62869d9a000f1ac751f",
"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": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:dockerfile": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:shared": "nqqyrvjz465mpn6ocxkgpb1mu"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-5b941d15-1932-4436-bc2b-bd94ca461f03/builder-5b941d15-1932-4436-bc2b-bd94ca461f030/aylnj41jb39pjbmfe8bihvmem",
"containerimage.config.digest": "sha256:5be5d145d17b56cd5e080a352f5a2afbb824cb1349d7c93cab3eda356bd371b6",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:82bfec9517bce23b9b45f9db659c96c65c2971ee020560e485c7f574957bcacb",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:82bfec9517bce23b9b45f9db659c96c65c2971ee020560e485c7f574957bcacb",
"image.name": "ghcr.io/graphql-hive/usage-ingestor:ebe9be3990d1597cbe8fe62869d9a000f1ac751f-arm64,ghcr.io/graphql-hive/usage-ingestor:console_1003-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": "ebe9be3990d1597cbe8fe62869d9a000f1ac751f",
"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": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:dockerfile": "nqqyrvjz465mpn6ocxkgpb1mu",
"local-sessionid:shared": "nqqyrvjz465mpn6ocxkgpb1mu"
},
"locals": [
{
"name": "context"
},
{
"name": "dist"
},
{
"name": "dockerfile"
},
{
"name": "shared"
}
]
},
"environment": {
"platform": "linux/arm64"
}
}
},
"buildx.build.ref": "builder-5b941d15-1932-4436-bc2b-bd94ca461f03/builder-5b941d15-1932-4436-bc2b-bd94ca461f030/js3i1bkpdmt62xu4l53v1pnci",
"containerimage.config.digest": "sha256:f8a543d2ad83a834c59d44740085e86b82cc7869db7917788e10e9fe67c2e224",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:c4cda4d18f97914cf61c0eb2f5c90cf571cdea8a97a47384c146951075b8482d",
"size": 2075,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
"containerimage.digest": "sha256:c4cda4d18f97914cf61c0eb2f5c90cf571cdea8a97a47384c146951075b8482d",
"image.name": "ghcr.io/graphql-hive/webhooks:ebe9be3990d1597cbe8fe62869d9a000f1ac751f-arm64,ghcr.io/graphql-hive/webhooks:console_1003-arm64"
}
} |
if (process.env.RUN_AGAINST_LOCAL_SERVICES === '1') { | ||
process.env.SUPERTOKENS_API_KEY = process.env.SUPERTOKENS_API_KEY ?? 'bubatzbieber6942096420'; | ||
process.env.SUPERTOKENS_CONNECTION_URI = | ||
process.env.SUPERTOKENS_CONNECTION_URI ?? 'http://localhost:3567'; | ||
// It seems that this has to be set in the environment that the cypress cli is executed from. | ||
// process.env.CYPRESS_BASE_URL = process.env.CYPRESS_BASE_URL ?? 'http://localhost:3000'; | ||
} | ||
|
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.
Remove this (and package script) and rebase once #6475 is merged.
cypress/e2e/laboratory/_cy.ts
Outdated
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 tried creating a laboratory domain of its sub sections and co-located the Cypress helpers.
I can undo this change if its out of scope or worse than the previous setup.
cypress/support/dedent.ts
Outdated
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.
Moved this to its own module since its just its own lib.
cypress/support/monaco.ts
Outdated
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.
Created a monaco lib to keep this generic utility away from specific monaco instances.
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe changes update the Cypress configuration and testing utilities by introducing a conditional block in the Cypress config to set environment variables for local services. A new namespace, Changes
Sequence Diagram(s)sequenceDiagram
participant Test
participant cyLab as cyLaboratory
participant Editor as GraphiQL Editor
Test->>cyLab: updateEditorValue(value)
cyLab->>Editor: Access CodeMirror, set value
Editor-->>cyLab: Acknowledge update
cyLab-->>Test: Confirm value update
sequenceDiagram
participant Test
participant SetContent as setMonacoEditorContents
participant Window
participant Monaco as Monaco Editor Instance
Test->>SetContent: Call setMonacoEditorContents(editorCyName, text)
SetContent->>Window: Wait for editor element & access window.Monaco
Window-->>SetContent: Return editor instances
SetContent->>Monaco: Find matching editor and set text
Monaco-->>SetContent: Confirm content update
SetContent-->>Test: Operation complete
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 (
|
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 (8)
package.json (1)
80-80
: Consider pinning the cypress-real-events version.Using
^1.14.0
could lead to unexpected updates. Consider pinning to an exact version for better reproducibility.- "cypress-real-events": "^1.14.0", + "cypress-real-events": "1.14.0",cypress/support/monaco.ts (2)
7-7
: Consider type safety improvements for Monaco editor access.The
(win as any).monaco
cast bypasses type checking. Consider using a more type-safe approach.- const editor = (win as any).monaco.editor + interface MonacoWindow extends Window { + monaco: { + editor: { + getEditors(): Array<{ + getContainerDomNode(): HTMLElement; + setValue(value: string): void; + }>; + }; + }; + } + const editor = (win as MonacoWindow).monaco.editor
14-16
: Enhance error message with more context.The error message could be more helpful by including the
editorCyName
in the message.- throw new Error('Monaco editor not found on the window or frames[0]'); + throw new Error(`Monaco editor not found for data-cy="${editorCyName}"`);cypress/e2e/laboratory/_cy.ts (3)
8-11
: Improve type safety for CodeMirror access.The CodeMirror instance is accessed using
any
type. Consider using proper types.+ interface CodeMirrorEditor { + CodeMirror: { + setValue(value: string): void; + getValue(): string; + }; + } - const editor = ($editor[0] as any).CodeMirror; + const editor = ($editor[0] as CodeMirrorEditor).CodeMirror;
52-60
: Consider non-recursive implementation for closeTabsUntilOneLeft.The recursive implementation could be replaced with a simpler while loop to avoid potential stack overflow.
export function closeTabsUntilOneLeft() { - cy.get('li.graphiql-tab').then($tabs => { - if ($tabs.length > 1) { - closeActiveTab(); - // Recurse until there's only one tab left - return closeTabsUntilOneLeft(); - } - }); + cy.get('li.graphiql-tab').then($tabs => { + const closeTabs = () => { + if ($tabs.length > 1) { + closeActiveTab(); + cy.get('li.graphiql-tab').then($newTabs => { + $tabs = $newTabs; + closeTabs(); + }); + } + }; + closeTabs(); + });
63-79
: Consider using an enum for selector constants.The selectors object could be defined as an enum or const enum for better type safety and maintainability.
- export const selectors = { + export const enum Selectors { + ButtonGraphiQLPreflight = '[aria-label*="Preflight Script"]', + ButtonModalCy = 'preflight-modal-button', + // ... rest of the selectors + }packages/web/app/src/lib/preflight/graphiql-plugin.tsx (1)
649-669
: LGTM! Comprehensive TypeScript validation enabled.The configuration enables thorough TypeScript validation with strict mode and modern JavaScript features. Consider documenting these settings in a configuration file or README to help other developers understand the validation rules.
Add a comment block explaining the TypeScript validation settings:
+ // Enable comprehensive TypeScript validation with strict mode + // - Semantic and syntax validation for better error detection + // - Modern JavaScript features (ESNext) with DOM types + // - Strict checks for improved code quality monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({cypress/support/dedent.ts (1)
25-44
: Consider optimizing the indentation detection logic.While the implementation is correct, there are a few potential improvements:
- The TypeScript type narrowing comment could be more descriptive
- The indentation detection could be more robust by handling mixed indentation
Consider this alternative implementation:
- const m = mindent; // appease TypeScript + const m = mindent; // TypeScript needs this assignment to narrow the type from 'number | null' to 'number' result = lines.map(l => (l[0] === ' ' || l[0] === '\t' ? l.slice(m) : l)).join('\n');Additionally, consider adding a warning when mixed indentation (spaces and tabs) is detected:
const lines = result.split('\n'); let mindent: null | number = null; + let hasSpaces = false; + let hasTabs = false; for (const l of lines) { const m = l.match(/^(\s+)\S+/); if (m) { + if (m[1].includes(' ')) hasSpaces = true; + if (m[1].includes('\t')) hasTabs = true; const indent = m[1].length; if (!mindent) { // this is the first indented line mindent = indent; } else { mindent = Math.min(mindent, indent); } } } + + if (hasSpaces && hasTabs) { + console.warn('Mixed indentation detected: both spaces and tabs are used'); + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (12)
cypress.config.ts
(1 hunks)cypress/e2e/laboratory/_cy.ts
(1 hunks)cypress/e2e/laboratory/collections.cy.ts
(9 hunks)cypress/e2e/laboratory/preflight.cy.ts
(16 hunks)cypress/e2e/laboratory/tabs.cy.ts
(2 hunks)cypress/support/dedent.ts
(1 hunks)cypress/support/e2e.ts
(1 hunks)cypress/support/monaco.ts
(1 hunks)cypress/support/testkit.ts
(0 hunks)package.json
(2 hunks)packages/web/app/src/lib/preflight/graphiql-plugin.tsx
(2 hunks)tsconfig.json
(1 hunks)
💤 Files with no reviewable changes (1)
- cypress/support/testkit.ts
✅ Files skipped from review due to trivial changes (1)
- cypress/support/e2e.ts
⏰ Context from checks skipped due to timeout of 90000ms (10)
- GitHub Check: test / unit
- GitHub Check: typescript / typecheck
- GitHub Check: static-analysis / analyze (typescript)
- GitHub Check: storybook-preview / deployment
- 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
- GitHub Check: SonarCloud
🔇 Additional comments (11)
cypress.config.ts (1)
11-17
: Consider moving environment variable configuration to a separate file.The local service configuration block could be moved to a dedicated configuration file to improve maintainability and separation of concerns.
Also, the commented-out
CYPRESS_BASE_URL
line suggests a potential issue with environment variable configuration.Please verify if the
CYPRESS_BASE_URL
needs to be set here or if it's correctly handled through the CLI command inpackage.json
.tsconfig.json (1)
6-6
: LGTM! Types configuration is correct.The addition of "cypress-real-events" types is necessary for TypeScript support.
package.json (2)
49-49
: LGTM! New script enhances local testing capabilities.The script correctly sets up the environment for local end-to-end testing.
47-49
: Verify test coverage for TypeScript validation.The PR is marked as draft due to missing tests. Consider adding end-to-end tests that verify the TypeScript validation functionality in the laboratory editor.
Would you like help generating test cases for the TypeScript validation feature?
cypress/e2e/laboratory/tabs.cy.ts (1)
1-35
: LGTM!The changes correctly implement the new cyLaboratory namespace while maintaining the existing test logic.
cypress/e2e/laboratory/collections.cy.ts (1)
1-250
: LGTM!The changes correctly implement the new cyLaboratory namespace while maintaining the existing test logic and coverage.
cypress/e2e/laboratory/preflight.cy.ts (1)
54-66
: 🛠️ Refactor suggestionImprove test reliability and fix type issues.
The test case has the following issues:
- The hardcoded delay (
cy.wait(1000)
) could make the test flaky.- The
@ts-expect-error
annotation suggests a type issue withrealPress
.Apply this diff to improve test reliability:
- cy.wait(1000); // :( + // Wait for TypeScript validation to complete + cy.contains(tsErrorMessage, { timeout: 5000 });Let's verify if there's a better way to handle keyboard events in Cypress:
✅ Verification successful
🌐 Web query:
What is the recommended way to handle keyboard events in Cypress? Are there any alternatives to cypress-real-events?
💡 Result:
The recommended approach for handling keyboard events in Cypress involves a combination of built-in commands and specialized plugins depending on testing requirements: ## Core Cypress Methods For most use cases: 1. **`.type()` command** handles simulated keyboard input with automatic event sequencing: - Fires `keydown`, `keypress`, `input`, and `keyup` events[1] - Supports special sequences like `{enter}` and modifier keys (`{ctrl}`, `{alt}`)[9] ```javascript cy.get('input').type('Hello{enter}') // Types text and presses Enter ``` 2. **`.trigger()`** manually dispatches events but has limitations: - Only creates generic `Event` objects without native `keyCode`/`code` properties[4] - Requires manual event configuration ## Real Event Simulation (cypress-real-events) When testing requires authentic browser interactions: - **Chromium-only solution** using Chrome DevTools Protocol[8] - Key features: ```javascript cy.get('input').realType('Text') // Native keystrokes cy.realPress('Tab') // Actual tab navigation cy.realPress(['Meta', 'A']) // Key combinations ``` - Advantages: - Generates trusted (`isTrusted: true`) events[8] - Handles focus management like real users[10] - Supports hover states and system dialogs | Feature | Built-in Commands | cypress-real-events | |-----------------------|-------------------|---------------------| | Trusted Events | ❌ | ✅ | | Cross-browser Support | ✅ | ❌ (Chromium only) | | Physical Key Presses | ❌ | ✅ | ## Alternatives & Workarounds 1. **Focus management**: ```javascript cy.get('input').focus().type('text') // Ensure element focus ``` 2. **Custom event dispatching** (for specific key properties): ```javascript cy.get('input').trigger('keydown', { key: 'a', code: 'KeyA', keyCode: 65 }) ``` 3. **Community plugins**: - `cypress-plugin-tab` for tab navigation[10] - `cypress-keycloak-commands` for specialized auth flows For most projects, combining native Cypress commands with selective use of cypress-real-events provides optimal coverage while maintaining cross-browser compatibility where needed[1][8]. Reserve low-level event triggering for edge cases requiring specific keyboard property validation[4]. Citations: - 1: https://docs.cypress.io/api/commands/type - 2: https://dev.to/samelawrence/my-favorite-cytype-tips-and-tricks-3166 - 3: https://betterstack.com/community/comparisons/cypress-alternative/ - 4: https://github.com/cypress-io/cypress/issues/29040 - 5: https://glebbahmutov.com/blog/how-to-pick-cypress-plugins/ - 6: https://www.lambdatest.com/blog/handling-touch-and-mouse-events-in-cypress/ - 7: https://www.browserstack.com/guide/handle-click-events-in-cypress - 8: https://github.com/dmtrKovalenko/cypress-real-events - 9: https://www.lambdatest.com/learning-hub/cypress-tips-and-tricks - 10: https://platform.text.com/resource-center/updates/cypress-axe-automated-testing
Update test to wait on validations and resolve TypeScript issues
- Replace the hardcoded delay (
cy.wait(1000)
) with an explicit wait for the expected error message (e.g. usingcy.contains(tsErrorMessage, { timeout: 5000 })
).- Investigate the TypeScript error on
realPress
: ensure you’re installing and importing the correct type definitions (or update them as needed) so that the plugin’s API is recognized without needing@ts-expect-error
.packages/web/app/src/lib/preflight/graphiql-plugin.tsx (1)
107-112
: LGTM! Enhanced editor features enabled.The Monaco editor configuration enables essential features for a better coding experience:
- Quick suggestions and auto-completion
- Code folding based on indentation
cypress/support/dedent.ts (3)
6-23
: LGTM! Robust string interpolation implementation.The implementation correctly handles raw template strings, escape sequences, and interpolation values.
46-52
: LGTM! Clean final string processing.The implementation correctly handles whitespace trimming and preserves escaped newlines in the right order.
1-4
: Consider resolving moduleResolution issues instead of copying code.While the implementation is properly attributed, copying code due to moduleResolution issues might lead to maintenance overhead and missed updates from the original package.
Let's verify if the moduleResolution issues can be resolved:
✅ Verification successful
🏁 Script executed:
#!/bin/bash # Check if dedent package is already listed in package.json if ! grep -q '"dedent":' package.json; then # Try installing dedent package to verify if it works npm install --save-dev dedent # Check TypeScript compilation npx tsc --noEmit fiLength of output: 1641
Module Resolution Conflict Prevents Switching from Local Implementation
The attempt to install the dedent package failed with a dependency resolution error related to ESLint and eslint-plugin-cypress. This confirms that the moduleResolution issues preventing the use of the package still exist. Therefore, until you update your dependency tree (e.g., upgrading ESLint to meet peer requirements) or adjust the conflicting packages, using the local implementation in
cypress/support/dedent.ts
remains the most viable workaround.
- The dedent package installation fails due to a peer dependency conflict (ESLint v8 vs. eslint-plugin-cypress expecting ESLint ≥9).
- Upgrading these dependencies might resolve the issue, but it could have wider implications.
- Retaining the local dedent implementation is acceptable for now given the current dependency constraints.
it('code is validated with TypeScript', () => { | ||
const tsErrorMessage = "Type 'string' is not assignable to type 'number'."; | ||
const script = 'let a = 1; a = ""'; | ||
cyp.setEditorContent(script); | ||
cy.wait(1000); // :( | ||
cy.dataCy(s.modal.editorCy) | ||
.find('textarea') | ||
.focus() | ||
// Followed instructions but does not work https://github.com/dmtrKovalenko/cypress-real-events?tab=readme-ov-file#installation | ||
// @ts-expect-error | ||
.realPress(['Alt', 'F8']); | ||
cy.contains(tsErrorMessage); | ||
}); |
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.
Given the noisy diff caused by refactoring, highlighting that here is the new test for this feature.
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
🔭 Outside diff range comments (1)
cypress/e2e/laboratory/preflight.cy.ts (1)
267-292
:🧩 Analysis chain
Add security tests for header injection.
The current test suite verifies header substitution but doesn't validate against header injection attacks. Consider adding tests to ensure that malicious header values are properly sanitized.
Consider adding these test cases:
it('header placeholders are substituted with environment variables', () => { // ... existing test code ... }); + +it('prevents header injection attacks', () => { + cy.dataCy('toggle-preflight').click(); + cy.get('[data-name="headers"]').click(); + // Test with potentially malicious header values + cy.get('.graphiql-editor-tool .graphiql-editor:last-child textarea').type( + '{ "__test": "{{foo}}\r\nMalicious-Header: value" }', + { + force: true, + parseSpecialCharSequences: false, + } + ); + cy.dataCy('env-editor-mini').within(() => { + cy.get('textarea').type('{"foo":"injected"}', { + force: true, + parseSpecialCharSequences: false, + }); + }); + + // Verify that header injection is prevented + cy.intercept({ + method: 'POST', + headers: { + __test: 'injected\r\nMalicious-Header: value', + }, + }).as('post'); + cy.get('.graphiql-execute-button').click(); + cy.wait('@post'); +});
🏁 Script executed:
#!/bin/bash # Search for header sanitization in the codebase rg -A 5 'headers\.append|headers\.set' --type tsLength of output: 4757
Attention: Missing Security Validation for Header Injection
The current test in cypress/e2e/laboratory/preflight.cy.ts only verifies header substitution against environment variables and does not check for header injection scenarios. Our codebase (as seen with calls to headers.append and headers.set) lacks explicit sanitization checks against header injection attacks. Consider adding dedicated tests (for example, using malicious characters to attempt header injection) to ensure that the application properly escapes or sanitizes header values.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
cypress/e2e/laboratory/preflight.cy.ts
(16 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (10)
- GitHub Check: static-analysis / analyze (typescript)
- GitHub Check: typescript / typecheck
- GitHub Check: static-analysis / analyze (javascript)
- GitHub Check: storybook-preview / deployment
- GitHub Check: test / unit
- GitHub Check: build / dockerize (linux/arm64)
- GitHub Check: build / dockerize (linux/amd64)
- GitHub Check: code-style / eslint-and-prettier
- GitHub Check: alpha / cli-artifacts
- GitHub Check: SonarCloud
🔇 Additional comments (1)
cypress/e2e/laboratory/preflight.cy.ts (1)
1-7
: LGTM! Clean import refactoring.The imports have been refactored to use the new
cyLaboratory
namespace, and the code introduces clear aliases (s
andcyp
) for better readability.
it('code is validated with TypeScript', () => { | ||
const tsErrorMessage = "Type 'string' is not assignable to type 'number'."; | ||
const script = 'let a = 1; a = ""'; | ||
cyp.setEditorContent(script); | ||
cy.wait(1000); // :( | ||
cy.dataCy(s.modal.editorCy) | ||
.find('textarea') | ||
.focus() | ||
// @ts-expect-error - Followed instructions but does not work https://github.com/dmtrKovalenko/cypress-real-events?tab=readme-ov-file#installation | ||
.realPress(['Alt', 'F8']); | ||
cy.contains(tsErrorMessage); | ||
}); |
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.
🛠️ Refactor suggestion
Replace hardcoded wait with proper assertions.
The test has several potential issues:
- Using a hardcoded
wait(1000)
is an anti-pattern in Cypress and could make the test flaky. - The keyboard shortcut
Alt+F8
might not work consistently across different platforms.
Consider this refactor:
it('code is validated with TypeScript', () => {
const tsErrorMessage = "Type 'string' is not assignable to type 'number'.";
const script = 'let a = 1; a = ""';
cyp.setEditorContent(script);
- cy.wait(1000); // :(
+ // Wait for TypeScript validation to complete
+ cy.get(s.modal.editorCy).should('exist');
+ cy.get('.monaco-editor').should('exist');
cy.dataCy(s.modal.editorCy)
.find('textarea')
.focus()
// @ts-expect-error - Followed instructions but does not work https://github.com/dmtrKovalenko/cypress-real-events?tab=readme-ov-file#installation
.realPress(['Alt', 'F8']);
- cy.contains(tsErrorMessage);
+ // Wait for error message to appear and verify it
+ cy.contains(tsErrorMessage).should('be.visible');
});
Additionally, consider adding a comment explaining the keyboard shortcut's purpose and documenting any platform-specific considerations.
📝 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.
it('code is validated with TypeScript', () => { | |
const tsErrorMessage = "Type 'string' is not assignable to type 'number'."; | |
const script = 'let a = 1; a = ""'; | |
cyp.setEditorContent(script); | |
cy.wait(1000); // :( | |
cy.dataCy(s.modal.editorCy) | |
.find('textarea') | |
.focus() | |
// @ts-expect-error - Followed instructions but does not work https://github.com/dmtrKovalenko/cypress-real-events?tab=readme-ov-file#installation | |
.realPress(['Alt', 'F8']); | |
cy.contains(tsErrorMessage); | |
}); | |
it('code is validated with TypeScript', () => { | |
const tsErrorMessage = "Type 'string' is not assignable to type 'number'."; | |
const script = 'let a = 1; a = ""'; | |
cyp.setEditorContent(script); | |
// Wait for TypeScript validation to complete | |
cy.get(s.modal.editorCy).should('exist'); | |
cy.get('.monaco-editor').should('exist'); | |
cy.dataCy(s.modal.editorCy) | |
.find('textarea') | |
.focus() | |
// @ts-expect-error - Followed instructions but does not work https://github.com/dmtrKovalenko/cypress-real-events?tab=readme-ov-file#installation | |
.realPress(['Alt', 'F8']); | |
// Wait for error message to appear and verify it | |
cy.contains(tsErrorMessage).should('be.visible'); | |
}); |
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 tried this but it doens't work. Getting this to work in Cypress required hacking around. I'll leave a comment making the point that we know its hacky.
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.
@jasonkuhrt Understood, thanks for the clarification. I apologize for the incorrect suggestion. You're right about documenting the limitation.
(_/)/
(•-•) nods in understanding
/> <>
✏️ Learnings added
Learnt from: jasonkuhrt
PR: graphql-hive/console#6476
File: cypress/e2e/laboratory/preflight.cy.ts:0-0
Timestamp: 2025-02-06T19:32:04.951Z
Learning: TypeScript validation in Cypress tests for Monaco editor may require workarounds like hardcoded waits, as proper assertions may not work reliably.
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.
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)
package.json (2)
49-49
: New Script Addition: "test:e2e:local".
This script provides a clear and concise way to run Cypress tests against your local environment by explicitly setting CYPRESS_BASE_URL and RUN_AGAINST_LOCAL_SERVICES. It adheres to the PR's objective of improving local testing capabilities. Consider adding a brief note or updating your documentation (e.g., in a README) to inform developers about when and how to use this script.
80-80
: New Dev Dependency: "cypress-real-events".
Introducing "cypress-real-events" at version 1.14.0 is a good move for simulating realistic user interactions in your E2E tests—especially relevant given the enhancements to the laboratory editor validation. Ensure that its usage is clearly demonstrated in your test files and that any setup requirements (if not already documented) are communicated to your team.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (1)
package.json
(2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (12)
- GitHub Check: storybook-preview / deployment
- GitHub Check: test / unit
- GitHub Check: typescript / typecheck
- GitHub Check: static-analysis / analyze (typescript)
- GitHub Check: static-analysis / analyze (javascript)
- GitHub Check: db-types / diff
- GitHub Check: test / db-migrations
- GitHub Check: alpha / cli-artifacts
- GitHub Check: build / dockerize (linux/arm64)
- GitHub Check: build / dockerize (linux/amd64)
- GitHub Check: code-style / eslint-and-prettier
- GitHub Check: SonarCloud
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)
cypress/e2e/laboratory/preflight.cy.ts
(16 hunks)cypress/tsconfig.json
(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (10)
- GitHub Check: alpha / cli-artifacts
- GitHub Check: typescript / typecheck
- GitHub Check: test / unit
- GitHub Check: storybook-preview / deployment
- GitHub Check: static-analysis / analyze (typescript)
- 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: SonarCloud
🔇 Additional comments (3)
cypress/tsconfig.json (1)
5-5
: LGTM! Configuration updated correctly.The addition of "cypress-real-events" to the types array properly enables TypeScript support for the cypress-real-events library.
cypress/e2e/laboratory/preflight.cy.ts (2)
24-24
: LGTM! Well-organized test structure.The tests are logically grouped into clear describe blocks that separate different aspects of functionality:
- Preflight Tab
- Preflight Modal
- Execution
This organization makes the test suite easy to understand and maintain.
Also applies to: 45-45, 187-187
54-61
:⚠️ Potential issueReplace hardcoded wait with proper assertions.
The test has several potential issues:
- Using a hardcoded
cy.wait(1000)
is an anti-pattern in Cypress and could make the test flaky- The keyboard shortcut
Alt+F8
might not work consistently across different platformsApply this diff to make the test more robust:
it('code is validated with TypeScript', () => { const tsErrorMessage = "Type 'string' is not assignable to type 'number'."; const script = 'let a = 1; a = ""'; cyp.setEditorContent(script); - cy.wait(1000); // :( + // Wait for TypeScript validation to complete + cy.get(s.modal.editorCy).should('exist'); + cy.get('.monaco-editor').should('exist') + cy.get('.monaco-editor .error-widget').should('exist'); cy.dataCy(s.modal.editorCy) .find('textarea') .focus() .realPress(['Alt', 'F8']); - cy.contains(tsErrorMessage); + // Wait for error message to appear and verify it + cy.contains(tsErrorMessage).should('be.visible');Additionally, consider adding a comment explaining the keyboard shortcut's purpose and documenting any platform-specific considerations.
Likely invalid or redundant 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.
Actionable comments posted: 0
🧹 Nitpick comments (2)
cypress/e2e/laboratory/_cy.ts (2)
8-11
: Improve type safety when accessing CodeMirror instance.The current implementation uses type assertion to
any
which bypasses TypeScript's type checking. Consider adding proper type definitions for CodeMirror.+// Add at the top of the file +interface CodeMirrorEditor { + CodeMirror: { + setValue: (value: string) => void; + getValue: () => string; + }; +} export function updateEditorValue(value: string) { cy.get('.graphiql-query-editor .cm-s-graphiql').then($editor => { - const editor = ($editor[0] as any).CodeMirror; + const editor = ($editor[0] as CodeMirrorEditor).CodeMirror; editor.setValue(value); }); }Also applies to: 18-21
52-60
: Optimize tab closing logic to prevent potential stack overflow.The recursive implementation could cause stack overflow with many tabs. Consider using a loop instead.
export function closeTabsUntilOneLeft() { - cy.get('li.graphiql-tab').then($tabs => { - if ($tabs.length > 1) { - closeActiveTab(); - // Recurse until there's only one tab left - return closeTabsUntilOneLeft(); - } + cy.get('li.graphiql-tab').then(function closeTabs($tabs) { + if ($tabs.length <= 1) return; + closeActiveTab(); + cy.get('li.graphiql-tab').then(closeTabs); }); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (5)
cypress/e2e/laboratory/_cy.ts
(1 hunks)cypress/e2e/laboratory/preflight.cy.ts
(18 hunks)cypress/support/monaco.ts
(1 hunks)cypress/tsconfig.json
(1 hunks)package.json
(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- cypress/tsconfig.json
- cypress/support/monaco.ts
- package.json
⏰ Context from checks skipped due to timeout of 90000ms (10)
- GitHub Check: storybook-preview / deployment
- GitHub Check: alpha / cli-artifacts
- 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: SonarCloud
🔇 Additional comments (5)
cypress/e2e/laboratory/_cy.ts (2)
62-80
: LGTM! Well-organized selectors.The selectors are well-structured and follow a consistent naming convention.
84-93
: LGTM! Clean implementation of editor content management.The functions are well-organized and follow DRY principles.
cypress/e2e/laboratory/preflight.cy.ts (3)
53-60
: Replace hardcoded wait with proper assertions.The previous review comment about replacing the hardcoded wait with proper assertions is still valid.
23-44
: LGTM! Well-organized test structure.The tests are logically grouped with clear descriptions and consistent patterns.
173-183
: LGTM! Robust error handling tests.The error cases are well-covered with specific assertions.
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)
cypress/e2e/laboratory/preflight.cy.ts (1)
53-61
: Document the TypeScript validation workaround.The test includes a hardcoded wait and keyboard shortcut that might be platform-dependent. While this is a known limitation (as per retrieved learnings), it should be documented more thoroughly.
const script = 'let a = 1; a = ""'; cyp.setEditorContent(script); - // Hack: Seemingly only way to reliably interact with the monaco text area from Cypress. + // HACK: Monaco editor's TypeScript validation is challenging to test in Cypress: + // 1. The hardcoded wait is necessary as there's no reliable way to detect when validation completes + // 2. The Alt+F8 shortcut might not work on all platforms (e.g., macOS) + // See: graphql-hive/console#6476 for more context cy.wait(1000); cy.dataCy(s.modal.editorCy).find('textarea').focus().realPress(['Alt', 'F8']); cy.contains(tsErrorMessage);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (1)
cypress/e2e/laboratory/preflight.cy.ts
(18 hunks)
🧰 Additional context used
📓 Learnings (1)
cypress/e2e/laboratory/preflight.cy.ts (1)
Learnt from: jasonkuhrt
PR: graphql-hive/console#6476
File: cypress/e2e/laboratory/preflight.cy.ts:0-0
Timestamp: 2025-02-06T19:32:05.091Z
Learning: TypeScript validation in Cypress tests for Monaco editor may require workarounds like hardcoded waits, as proper assertions may not work reliably.
⏰ Context from checks skipped due to timeout of 90000ms (10)
- GitHub Check: test / unit
- GitHub Check: typescript / typecheck
- GitHub Check: static-analysis / analyze (typescript)
- GitHub Check: storybook-preview / deployment
- 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
- GitHub Check: SonarCloud
🔇 Additional comments (3)
cypress/e2e/laboratory/preflight.cy.ts (3)
1-6
: LGTM! Clean refactor of imports and selector references.The code has been improved by:
- Importing utilities from dedicated modules
- Using a consistent selector reference through
cyLaboratory.preflight.selectors
50-51
: LGTM! Consistent use of editor content setting methods.The code has been standardized to use
cyp.setEditorContent
andcyp.setEnvironmentEditorContent
throughout the test file, improving maintainability.Also applies to: 64-65, 76-77, 98-99, 154-155, 165-166, 175-176, 181-182, 195-196, 219-220, 247-251, 301-302, 328-334, 360-361, 379-387, 423-431
23-24
: LGTM! Improved test organization.The test suites have been renamed for better clarity:
- "Laboratory > Preflight Script" → "Preflight Tab"
- "Preflight Script Modal" → "Preflight Modal"
Also applies to: 44-45
Great point, I'll look into this to see what our options are.
@n1ru4l oh yeah, currently |
packages/web/app/src/lib/preflight/allowed-globals.ts is the file you are looking for. I hope there is a way for adding these without having to pluck the dom typings 😢 |
@n1ru4l awesome thanks. My hope is we'll just need to list them in the tsconfig lib settings given to Monaco, and that there is a 1:1 between dom lib names and those globals. tbd... |
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: 2
🧹 Nitpick comments (4)
packages/web/app/src/lib/preflight/components/PreflightModal.tsx (1)
59-68
: Remove or clarify commented-out code for maintainability.Lines 67–68 appear to be leftover or experimental and are commented out, which can lead to confusion. Removing or clarifying these lines helps keep the codebase clean and more understandable.
packages/web/app/src/lib/preflight/graphiql-plugin.tsx (3)
23-39
: Consider removing commented-out code.The commented-out icon class in
classes
object is marked as unused. If it's no longer needed, it should be removed to maintain code cleanliness.const classes = { monacoMini: clsx('h-32 *:rounded-md *:bg-[#10151f]'), - // todo: was unused, commented out for now, remove? - // icon: clsx('absolute -left-5 top-px'), };
530-538
: Consider adding JSON schema validation for environment variables.Since the environment editor is used for JSON input, consider adding JSON schema validation to catch errors early and provide better autocompletion.
<EnvironmentEditor height={128} value={preflight.environmentVariables} onChange={value => preflight.setEnvironmentVariables(value ?? '')} className={classes.monacoMini} wrapperProps={{ ['data-cy']: 'env-editor-mini', }} + options={{ + // Enable JSON validation + formatOnPaste: true, + formatOnType: true, + // Add schema validation + schemas: [{ + uri: "preflight-env-schema.json", + fileMatch: ["*"], + schema: { + type: "object", + additionalProperties: { + type: ["string", "number", "boolean", "null"] + } + } + }] + }} />
381-384
: Improve documentation for sandbox permissions.The comment about sandbox permissions in DEV mode could be more explicit about security implications.
-/** - * In DEV we need to use "allow-same-origin", as otherwise the embed can not instantiate the webworker (which is loaded from an URL). - * In PROD the webworker is not - */ +/** + * Sandbox permissions: + * - DEV: Requires "allow-same-origin" for webworker instantiation from URL + * - PROD: Uses bundled webworker, so "allow-same-origin" is not needed + * + * Security note: "allow-same-origin" is safe in DEV as the content is trusted + */
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
packages/web/app/src/lib/MonacoEditorReact/index.ts
(1 hunks)packages/web/app/src/lib/preflight/components/EditorTitle.tsx
(1 hunks)packages/web/app/src/lib/preflight/components/EnvironmentEditor.tsx
(1 hunks)packages/web/app/src/lib/preflight/components/LogLine.tsx
(1 hunks)packages/web/app/src/lib/preflight/components/PreflightModal.tsx
(1 hunks)packages/web/app/src/lib/preflight/components/ScriptEditor.tsx
(1 hunks)packages/web/app/src/lib/preflight/components/_defaultEditorProps.ts
(1 hunks)packages/web/app/src/lib/preflight/graphiql-plugin.tsx
(3 hunks)packages/web/app/src/lib/preflight/index.ts
(1 hunks)packages/web/app/src/lib/preflight/shared-types.ts
(1 hunks)packages/web/app/src/pages/target-laboratory.tsx
(1 hunks)
✅ Files skipped from review due to trivial changes (3)
- packages/web/app/src/lib/MonacoEditorReact/index.ts
- packages/web/app/src/lib/preflight/index.ts
- packages/web/app/src/pages/target-laboratory.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
packages/web/app/src/lib/preflight/shared-types.ts
[error] 6-9: The enum declaration should not be const
Const enums are not supported by bundlers and are incompatible with the 'isolatedModules' mode. Their use can lead to import inexistent values.
See TypeScript Docs for more details.
Safe fix: Turn the const enum into a regular enum.
(lint/suspicious/noConstEnum)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Mend Security Check
🔇 Additional comments (13)
packages/web/app/src/lib/preflight/components/PreflightModal.tsx (3)
87-151
: Ensure all required global declarations are included.You’ve declared many console and global API definitions here. Consider verifying that you’ve included all Preflight-specific global types you might rely on (e.g., setInterval, localStorage) to avoid potential runtime errors. Conversely, if some declarations are not actually used in this environment, pruning them can keep the code lean.
175-182
: Preventing modal closure on Escape while editing is helpful—double-check user expectations.You block the Escape key from closing the modal when users focus the Monaco editor. This is generally good, but confirm this aligns with user expectations in your design. Some might expect Escape to still close the modal unless code is actively being typed.
210-213
: Confirm no concurrency issues with run/stop flow.The code toggles execution based on the worker state. Ensure that rapid consecutive clicks, or potential race conditions in “running” → “aborting” → “running” transitions, are gracefully handled. Otherwise, you may end up in an inconsistent state if the worker has unhandled asynchronous tasks.
packages/web/app/src/lib/preflight/components/EditorTitle.tsx (1)
4-10
: Lightweight component usage looks good.This component nicely abstracts out a title style for editors. It's short, readable, and effectively uses the utility class function, so no issues spotted here.
packages/web/app/src/lib/preflight/components/_defaultEditorProps.ts (1)
4-17
: Great approach for shared editor defaults.Defining global editor props here centralizes styling and features. If you need environment-specific styling (e.g., read-only in certain contexts), consider making some fields dynamically configurable. Otherwise, this is a clean, straightforward default configuration.
packages/web/app/src/lib/preflight/components/EnvironmentEditor.tsx (2)
4-12
: LGTM! Well-configured JSON editor settings.The default props are well-configured for JSON editing with appropriate settings like disabled line numbers and 2-space indentation, which aligns with common JSON formatting conventions.
14-25
: LGTM! Clean component implementation.The component follows React best practices with proper props spreading order, ensuring that user-provided props can override defaults while maintaining type safety.
packages/web/app/src/lib/preflight/components/ScriptEditor.tsx (2)
19-30
: LGTM! Clean component implementation.The component follows React best practices with proper props spreading order, ensuring that user-provided props can override defaults while maintaining type safety.
4-17
: Verify TypeScript validation settings.The editor is configured well for JavaScript, but based on the PR objectives to improve TypeScript validation, we should verify if additional TypeScript-specific settings are needed.
Also, consider adding these TypeScript-specific settings to align with the PR objectives:
options: { ...defaultEditorProps.options, quickSuggestions: true, suggestOnTriggerCharacters: true, acceptSuggestionOnEnter: 'on', tabCompletion: 'on', folding: true, foldingStrategy: 'indentation', + // Enable TypeScript validation + diagnostics: true, + validate: true, },packages/web/app/src/lib/preflight/components/LogLine.tsx (2)
4-22
: LGTM! Well-structured error handling and type checking.The component implements proper type guards and error handling with Sentry integration. The conditional rendering logic is clean and maintainable.
24-29
: LGTM! Semantic color scheme.The color scheme follows common conventions for log levels (red for errors, yellow for warnings, etc.), enhancing readability and user experience.
packages/web/app/src/lib/preflight/shared-types.ts (1)
11-11
: LGTM! Clear type definition.The union type for LogRecord is well-defined and provides good type safety for different log entry types.
packages/web/app/src/lib/preflight/graphiql-plugin.tsx (1)
503-519
: Enhance TypeScript validation in the script editor.Based on the PR objectives to improve TypeScript validation, consider configuring the Monaco editor with TypeScript-specific options:
- Enable TypeScript validation while limiting suggestions to allowed APIs
- Configure the editor to flag TypeScript-specific syntax as errors
<ScriptEditor height={128} value={preflight.content} className={cn(classes.monacoMini, 'z-10')} wrapperProps={{ ['data-cy']: 'preflight-editor-mini', }} options={{ lineNumbers: 'off', domReadOnly: true, readOnly: true, hover: { enabled: false, }, + // Enable TypeScript validation + javascriptDefaults: { + validate: true, + // Limit suggestions to allowed APIs + suggest: { + includeCompletionsForModuleExports: false, + }, + }, + // Flag TypeScript-specific syntax as errors + typescript: { + validate: { + syntaxValidation: 'error', + }, + }, }} />Let's verify the allowed globals in Preflight:
✅ Verification successful
🏁 Script executed:
#!/bin/bash # Description: Check the allowed globals in Preflight cat packages/web/app/src/lib/preflight/allowed-globals.tsLength of output: 1055
Action: Enhance TypeScript validation in the Monaco editor configuration
The allowed globals list (from packages/web/app/src/lib/preflight/allowed-globals.ts) is intact and matches expectations. The proposed diff in —which adds TypeScript-specific options (enabling validation, restricting module export suggestions, and flagging syntax errors)—is consistent with the intent to restrict the editor’s suggestions to allowed APIs. No discrepancies were found with the allowed globals definition.
• Allowed globals are defined as expected.
• The reviewer’s suggestion to add TypeScript validation options in the ScriptEditor’s options is appropriate.
onContentChange(scriptEditorRef.current?.getValue() ?? ''); | ||
onEnvValueChange(envEditorRef.current?.getValue() ?? ''); | ||
toggle(); | ||
}, []); |
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.
🛠️ Refactor suggestion
Consider validating editor data before saving.
At the time of submission (handleSubmit), you capture script and environment values directly from the editors. If either editor content requires JSON or special parsing, introduce validation (or error messages) to catch invalid inputs before applying them globally.
// todo stop using enums | ||
export const enum PreflightWorkerState { | ||
running, | ||
ready, | ||
} |
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.
Convert const enum to regular enum or union type.
The static analysis tool correctly flags that const enums can cause issues with bundlers and the 'isolatedModules' mode. Consider these alternatives:
-// todo stop using enums
-export const enum PreflightWorkerState {
- running,
- ready,
-}
+// Option 1: Regular enum
+export enum PreflightWorkerState {
+ running,
+ ready,
+}
+
+// Option 2: Union type (preferred, aligns with TODO)
+export type PreflightWorkerState = 'running' | 'ready';
Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 Biome (1.9.4)
[error] 6-9: The enum declaration should not be const
Const enums are not supported by bundlers and are incompatible with the 'isolatedModules' mode. Their use can lead to import inexistent values.
See TypeScript Docs for more details.
Safe fix: Turn the const enum into a regular enum.
(lint/suspicious/noConstEnum)
Hey @n1ru4l, I made some progress.
|
Background
This brings TypeScript validation to the laboratory editor so that users have a better experience writing code, because the compiler will catch more of their mistakes for them.
Description
Monaco React has built in support for this so not much doing was needed.