Skip to content

Commit 0d7b42d

Browse files
Dont install peer dependencies automatically with npm in Docker (#412)
Co-authored-by: theguild-bot <[email protected]>
1 parent 17e7475 commit 0d7b42d

File tree

40 files changed

+8698
-1531
lines changed

40 files changed

+8698
-1531
lines changed

.changeset/yellow-peas-relax.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@graphql-hive/gateway': patch
3+
---
4+
5+
Dont install peer dependencies automatically with npm in Docker

.github/workflows/examples.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ jobs:
4545
- programmatic-batching
4646
- subscriptions-with-transforms
4747
- type-merging-batching
48+
- operation-field-permissions
4849
name: Convert ${{matrix.e2e}}
4950
runs-on: ubuntu-latest
5051
steps:

docker-bake.hcl

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,50 @@ target "gateway" {
2121
]
2222
}
2323

24+
target "gateway_bun" {
25+
context = "packages/gateway"
26+
dockerfile = "bun.Dockerfile"
27+
platforms = ["linux/amd64", "linux/arm64"]
28+
tags = formatlist("ghcr.io/graphql-hive/gateway:%s-bun", split(",", GATEWAY_TAGS))
29+
annotations = [
30+
"index:org.opencontainers.image.title=Hive Gateway on Bun",
31+
"index:org.opencontainers.image.description=GraphQL Gateway by The Guild that can act as a Apollo Federation Gateway or a Proxy Gateway for any GraphQL service.",
32+
"index:org.opencontainers.image.authors=The Guild",
33+
"index:org.opencontainers.image.licenses=MIT",
34+
"index:org.opencontainers.image.source=https://github.com/graphql-hive/gateway/tree/main/packages/gateway",
35+
"index:org.opencontainers.image.documentation=https://the-guild.dev/graphql/hive/docs/gateway/deployment/docker"
36+
]
37+
}
38+
2439
//
2540

2641
group "e2e" {
27-
targets = ["gateway_e2e", "gateway_e2e_openapi-javascript-wiki"]
42+
targets = [
43+
"gateway_e2e",
44+
"gateway_e2e_openapi-javascript-wiki",
45+
"gateway_e2e_operation-field-permissions"
46+
]
2847
}
2948

3049
group "e2e_bun" {
31-
targets = ["gateway_e2e_bun", "gateway_e2e_openapi-javascript-wiki_bun"]
50+
targets = [
51+
"gateway_e2e_bun",
52+
"gateway_e2e_openapi-javascript-wiki_bun",
53+
"gateway_e2e_operation-field-permissions_bun"
54+
]
3255
}
3356

3457
target "gateway_e2e" {
3558
context = "packages/gateway"
3659
dockerfile = "node.Dockerfile"
3760
tags = ["ghcr.io/graphql-hive/gateway:e2e"]
3861
}
39-
4062
target "gateway_e2e_bun" {
4163
context = "packages/gateway"
4264
dockerfile = "bun.Dockerfile"
4365
tags = ["ghcr.io/graphql-hive/gateway:e2e-bun"]
4466
}
67+
4568
target "gateway_e2e_openapi-javascript-wiki" {
4669
context = "e2e/openapi-javascript-wiki"
4770
dockerfile = "gateway.Dockerfile"
@@ -50,7 +73,6 @@ target "gateway_e2e_openapi-javascript-wiki" {
5073
"gateway_e2e": "target:gateway_e2e"
5174
}
5275
}
53-
5476
target "gateway_e2e_openapi-javascript-wiki_bun" {
5577
context = "e2e/openapi-javascript-wiki"
5678
dockerfile = "gateway_bun.Dockerfile"
@@ -60,17 +82,19 @@ target "gateway_e2e_openapi-javascript-wiki_bun" {
6082
}
6183
}
6284

63-
target "gateway_bun" {
64-
context = "packages/gateway"
65-
dockerfile = "bun.Dockerfile"
66-
platforms = ["linux/amd64", "linux/arm64"]
67-
tags = formatlist("ghcr.io/graphql-hive/gateway:%s-bun", split(",", GATEWAY_TAGS))
68-
annotations = [
69-
"index:org.opencontainers.image.title=Hive Gateway on Bun",
70-
"index:org.opencontainers.image.description=GraphQL Gateway by The Guild that can act as a Apollo Federation Gateway or a Proxy Gateway for any GraphQL service.",
71-
"index:org.opencontainers.image.authors=The Guild",
72-
"index:org.opencontainers.image.licenses=MIT",
73-
"index:org.opencontainers.image.source=https://github.com/graphql-hive/gateway/tree/main/packages/gateway",
74-
"index:org.opencontainers.image.documentation=https://the-guild.dev/graphql/hive/docs/gateway/deployment/docker"
75-
]
76-
}
85+
target "gateway_e2e_operation-field-permissions" {
86+
context = "e2e/operation-field-permissions"
87+
dockerfile = "gateway.Dockerfile"
88+
tags = ["ghcr.io/graphql-hive/gateway:e2e.operation-field-permissions"]
89+
contexts = {
90+
"gateway_e2e": "target:gateway_e2e"
91+
}
92+
}
93+
target "gateway_e2e_operation-field-permissions_bun" {
94+
context = "e2e/operation-field-permissions"
95+
dockerfile = "gateway_bun.Dockerfile"
96+
tags = ["ghcr.io/graphql-hive/gateway:e2e.operation-field-permissions-bun"]
97+
contexts = {
98+
"gateway_e2e_bun": "target:gateway_e2e_bun"
99+
}
100+
}

e2e/openapi-subgraph/openapi-subgraph.e2e.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createTenv, Service } from '@internal/e2e';
1+
import { createTenv, dockerHostName, Service } from '@internal/e2e';
22
import { beforeAll, describe, expect, it } from 'vitest';
33

44
describe('openapi-subgraph', () => {
@@ -10,7 +10,7 @@ describe('openapi-subgraph', () => {
1010
GQLService = await service('GQL');
1111
});
1212
function replaceDockerHostNamesBack(sdl?: string) {
13-
return sdl?.replaceAll('172.17.0.1', 'localhost');
13+
return sdl?.replaceAll(dockerHostName, 'localhost');
1414
}
1515
it('exposes the SDL correctly', async () => {
1616
const { result, output } = await composeWithMesh({
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
FROM gateway_e2e
2+
3+
RUN npm i @envelop/operation-field-permissions
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { useOperationFieldPermissions } from '@envelop/operation-field-permissions';
2+
import { defineConfig, GatewayContext } from '@graphql-hive/gateway';
3+
4+
export const gatewayConfig = defineConfig({
5+
plugins: () => [
6+
useOperationFieldPermissions({
7+
getPermissions(ctx: GatewayContext) {
8+
const auth = ctx.request.headers.get('authorization');
9+
if (
10+
auth ===
11+
'Bearer TOKEN' /** NOTE: proper token validity check goes here */
12+
) {
13+
// allow all fields
14+
return new Set(['*']);
15+
}
16+
// allow only introspection
17+
return new Set(['Query.registrationOpen']);
18+
},
19+
}) as any, // TODO: fix generic in envelop
20+
],
21+
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
FROM gateway_e2e_bun
2+
3+
RUN bun i @envelop/operation-field-permissions
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import {
2+
defineConfig,
3+
loadGraphQLHTTPSubgraph,
4+
} from '@graphql-mesh/compose-cli';
5+
import { Opts } from '@internal/testing';
6+
7+
const opts = Opts(process.argv);
8+
9+
export const composeConfig = defineConfig({
10+
subgraphs: [
11+
{
12+
sourceHandler: loadGraphQLHTTPSubgraph('users', {
13+
endpoint: `http://localhost:${opts.getServicePort('users')}/graphql`,
14+
}),
15+
},
16+
],
17+
});
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { createTenv } from '@internal/e2e';
2+
import { expect, it } from 'vitest';
3+
4+
const { gateway, service } = createTenv(__dirname);
5+
6+
it('should allow checking registration but disallow "me" when not authenticated', async () => {
7+
const { execute } = await gateway({
8+
supergraph: {
9+
with: 'mesh',
10+
services: [await service('users')],
11+
},
12+
});
13+
14+
await expect(
15+
execute({
16+
query: /* GraphQL */ `
17+
{
18+
registrationOpen
19+
}
20+
`,
21+
}),
22+
).resolves.toMatchInlineSnapshot(`
23+
{
24+
"data": {
25+
"registrationOpen": false,
26+
},
27+
}
28+
`);
29+
30+
await expect(
31+
execute({
32+
query: /* GraphQL */ `
33+
{
34+
me {
35+
name
36+
}
37+
}
38+
`,
39+
}),
40+
).resolves.toMatchInlineSnapshot(`
41+
{
42+
"data": null,
43+
"errors": [
44+
{
45+
"locations": [
46+
{
47+
"column": 11,
48+
"line": 3,
49+
},
50+
],
51+
"message": "Insufficient permissions for selecting 'Query.me'.",
52+
},
53+
{
54+
"locations": [
55+
{
56+
"column": 13,
57+
"line": 4,
58+
},
59+
],
60+
"message": "Insufficient permissions for selecting 'User.name'.",
61+
},
62+
],
63+
}
64+
`);
65+
});
66+
67+
it('should allow "me" when authenticated', async () => {
68+
const { execute } = await gateway({
69+
supergraph: {
70+
with: 'mesh',
71+
services: [await service('users')],
72+
},
73+
pipeLogs: 'gw.log',
74+
});
75+
76+
await expect(
77+
execute({
78+
query: /* GraphQL */ `
79+
{
80+
registrationOpen
81+
me {
82+
name
83+
}
84+
}
85+
`,
86+
headers: {
87+
authorization: 'Bearer TOKEN',
88+
},
89+
}),
90+
).resolves.toMatchInlineSnapshot(`
91+
{
92+
"data": {
93+
"me": {
94+
"name": "John",
95+
},
96+
"registrationOpen": false,
97+
},
98+
}
99+
`);
100+
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "@e2e/operation-field-permissions",
3+
"private": true,
4+
"dependencies": {
5+
"@envelop/core": "^5.0.2",
6+
"@envelop/operation-field-permissions": "^6.0.0",
7+
"@graphql-mesh/compose-cli": "^1.2.13",
8+
"graphql": "^16.10.0"
9+
}
10+
}

0 commit comments

Comments
 (0)