diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index acc61cffbc..bc75e98b02 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -271,6 +271,30 @@ jobs: failOnRequired: true debug: true + hackernews-docker-container: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4 + + - name: Setup env + uses: the-guild-org/shared-config/setup@main + with: + nodeVersion: 22 + packageManager: pnpm + + - name: Build Packages + run: pnpm build + + - name: Build Hackernews App + run: pnpm --filter=example-hackernews build + + - name: Isolate Docker Image Build Context + run: pnpm build:hackernews:docker + + - name: Build Hackernews Docker Image + run: docker compose -f .hackernews-deploy/docker-compose.yml build api + # TODO: have the example and packages use singleton nestjs dependencies # but without using .pnpmfile.cjs because it causes issues with renovate: https://github.com/dotansimha/graphql-yoga/pull/2622 # nestjs-apollo-federation-compatibility: diff --git a/.gitignore b/.gitignore index 347cc5aa84..236587c794 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ packages/graphql-yoga/src/graphiql-html.ts .tool-versions .mise.toml +.hackernews-deploy diff --git a/examples/hackernews/Dockerfile b/examples/hackernews/Dockerfile new file mode 100644 index 0000000000..581a69a0fc --- /dev/null +++ b/examples/hackernews/Dockerfile @@ -0,0 +1,23 @@ +FROM node:22-slim + +RUN apt-get update && apt-get install -y ca-certificates + +WORKDIR /usr/src/app + +COPY ./package.json /usr/src/app +COPY ./node_modules /usr/src/app/node_modules + +COPY ./dist/src/ /usr/src/app/ + +LABEL org.opencontainers.image.title="Hackernews GraphQL Server" +LABEL org.opencontainers.image.version=$RELEASE +LABEL org.opencontainers.image.description="A Hackernews clone built with GraphQL and graphql-yoga." +LABEL org.opencontainers.image.authors="The Guild" +LABEL org.opencontainers.image.vendor="Laurin Quast" +LABEL org.opencontainers.image.url="https://github.com/dotansimha/graphql-yoga/tree/main/examples/hackernews" +LABEL org.opencontainers.image.source="https://github.com/dotansimha/graphql-yoga/tree/main/examples/hackernews" + +ENV ENVIRONMENT production +ENV RELEASE $RELEASE + +ENTRYPOINT ["node", "main.js"] diff --git a/examples/hackernews/docker-compose.yml b/examples/hackernews/docker-compose.yml index 3feea56fa9..43bfc0eb88 100644 --- a/examples/hackernews/docker-compose.yml +++ b/examples/hackernews/docker-compose.yml @@ -19,5 +19,24 @@ services: ports: - '5432:5432' + api: + image: ${DOCKER_REGISTRY}yoga-hackernews${DOCKER_TAG} + build: + context: . + dockerfile: Dockerfile + networks: + - 'stack' + depends_on: + - db + environment: + PG_CONNECTION_STRING: postgres://postgres:postgres@db:5432/postgres + ports: + - '4000:4000' + healthcheck: + test: ['CMD', 'curl', '-f', 'http://localhost:3000/health'] + interval: 10s + timeout: 5s + retries: 5 + networks: stack: {} diff --git a/examples/hackernews/package.json b/examples/hackernews/package.json index d49b273ce3..f5758eb953 100644 --- a/examples/hackernews/package.json +++ b/examples/hackernews/package.json @@ -9,8 +9,9 @@ "files": [ "Dockerfile", "dist/src", + "docker-compose.yml", "package.json", - "prisma" + "README.md" ], "keywords": [], "scripts": { @@ -18,6 +19,7 @@ "check": "tsc --pretty --noEmit", "dev": "cross-env NODE_ENV=development node --loader=ts-node/esm --env-file .env --watch src/main.ts", "migrate": "pnpm drizzle-kit generate", + "postbuild": "npx cpy 'src/**/*.{json,sql}' ./dist/src --parents", "start": "ts-node src/main.ts" }, "dependencies": { @@ -29,6 +31,7 @@ "devDependencies": { "@types/node": "18.16.16", "@types/pg": "8.11.6", + "cpy-cli": "5.0.0", "cross-env": "7.0.3", "drizzle-kit": "0.22.7", "ts-node": "10.9.1", diff --git a/package.json b/package.json index 5ab4eabee5..976971ad5a 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "scripts": { "build": "pnpm --filter=@graphql-yoga/graphiql run build && pnpm --filter=@graphql-yoga/render-graphiql run build && pnpm --filter=graphql-yoga run generate-graphiql-html && bob build", "build-website": "pnpm build && cd website && pnpm build", + "build:hackernews:docker": "pnpm --filter=example-hackernews deploy --prod .hackernews-deploy", "changeset": "changeset", "check": "pnpm -r run check", "lint": "eslint --ignore-path .eslintignore --ext ts,js,tsx,jsx .", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1d6599b85c..575e349dc2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -744,6 +744,9 @@ importers: '@types/pg': specifier: 8.11.6 version: 8.11.6 + cpy-cli: + specifier: 5.0.0 + version: 5.0.0 cross-env: specifier: 7.0.3 version: 7.0.3 @@ -9600,6 +9603,15 @@ packages: resolution: {integrity: sha512-3scnzFj/94eb7y4wyXRWwvzLFaQp87yyfTnChIjlfYrVqp5lVO3E2hIJMeQIltUT0K2ZAB3An1qXcBmwGyvuwA==} engines: {node: '>=10'} + cpy-cli@5.0.0: + resolution: {integrity: sha512-fb+DZYbL9KHc0BC4NYqGRrDIJZPXUmjjtqdw4XRRg8iV8dIfghUX/WiL+q4/B/KFTy3sK6jsbUhBaz0/Hxg7IQ==} + engines: {node: '>=16'} + hasBin: true + + cpy@10.1.0: + resolution: {integrity: sha512-VC2Gs20JcTyeQob6UViBLnyP0bYHkBh6EiKzot9vi2DmeGlFT9Wd7VG3NBrkNx/jYvFBeyDOMMHdHQhbtKLgHQ==} + engines: {node: '>=16'} + cpy@9.0.1: resolution: {integrity: sha512-D9U0DR5FjTCN3oMTcFGktanHnAG5l020yvOCR1zKILmAyPP7I/9pl6NFgRbDcmSENtbK1sQLBz1p9HIOlroiNg==} engines: {node: ^12.20.0 || ^14.17.0 || >=16.0.0} @@ -11370,6 +11382,10 @@ packages: resolution: {integrity: sha512-8krCNHXvlCgHDpegPzleMq07yMYTO2sXKASmZmquEYWEmCx6J5UTRbp5RwMJkTJGtcQ44YpiUYUiN0b9mzy8Bw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + globby@13.2.2: + resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + globrex@0.1.2: resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} @@ -12764,6 +12780,10 @@ packages: resolution: {integrity: sha512-ojtSU++zLJ3jQG9bAYjg94w+/DOJtRyD7nPaerMFrBhmdVmiV5/exYH5t4uHga4G/95nT6hr1OJoKIFbYbrW5w==} engines: {node: '>=12.20'} + junk@4.0.1: + resolution: {integrity: sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==} + engines: {node: '>=12.20'} + just-diff-apply@5.5.0: resolution: {integrity: sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==} @@ -13362,6 +13382,10 @@ packages: memoize-one@6.0.0: resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} + meow@12.1.1: + resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} + engines: {node: '>=16.10'} + meow@6.1.1: resolution: {integrity: sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==} engines: {node: '>=8'} @@ -14410,6 +14434,10 @@ packages: resolution: {integrity: sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==} engines: {node: '>=12'} + p-map@6.0.0: + resolution: {integrity: sha512-T8BatKGY+k5rU+Q/GTYgrEf2r4xRMevAN5mtXc2aPc4rS1j3s+vWTaO2Wag94neXuCAUAs8cxBL9EeB5EA6diw==} + engines: {node: '>=16'} + p-reduce@3.0.0: resolution: {integrity: sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q==} engines: {node: '>=12'} @@ -20905,7 +20933,7 @@ snapshots: debug: 4.3.4(supports-color@9.2.3) espree: 9.6.0 globals: 13.19.0 - ignore: 5.2.4 + ignore: 5.3.1 import-fresh: 3.3.0 js-yaml: 4.1.0 minimatch: 3.1.2 @@ -25689,7 +25717,7 @@ snapshots: debug: 4.3.4(supports-color@9.2.3) eslint: 8.44.0 graphemer: 1.4.0 - ignore: 5.2.4 + ignore: 5.3.1 natural-compare-lite: 1.4.0 semver: 7.5.4 tsutils: 3.21.0(typescript@5.1.6) @@ -27732,6 +27760,22 @@ snapshots: nested-error-stacks: 2.1.1 p-event: 4.2.0 + cpy-cli@5.0.0: + dependencies: + cpy: 10.1.0 + meow: 12.1.1 + + cpy@10.1.0: + dependencies: + arrify: 3.0.0 + cp-file: 10.0.0 + globby: 13.2.2 + junk: 4.0.1 + micromatch: 4.0.5 + nested-error-stacks: 2.1.1 + p-filter: 3.0.0 + p-map: 6.0.0 + cpy@9.0.1: dependencies: arrify: 3.0.0 @@ -28896,7 +28940,7 @@ snapshots: builtins: 5.0.1 eslint: 8.44.0 eslint-plugin-es-x: 7.1.0(eslint@8.44.0) - ignore: 5.2.4 + ignore: 5.3.1 is-core-module: 2.13.1 minimatch: 3.1.2 resolve: 1.22.8 @@ -30090,7 +30134,15 @@ snapshots: dependencies: dir-glob: 3.0.1 fast-glob: 3.3.2 - ignore: 5.2.4 + ignore: 5.3.1 + merge2: 1.4.1 + slash: 4.0.0 + + globby@13.2.2: + dependencies: + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.1 merge2: 1.4.1 slash: 4.0.0 @@ -31960,6 +32012,8 @@ snapshots: junk@4.0.0: {} + junk@4.0.1: {} + just-diff-apply@5.5.0: {} just-diff@6.0.2: {} @@ -32822,6 +32876,8 @@ snapshots: memoize-one@6.0.0: {} + meow@12.1.1: {} + meow@6.1.1: dependencies: '@types/minimist': 1.2.2 @@ -34450,6 +34506,8 @@ snapshots: dependencies: aggregate-error: 4.0.1 + p-map@6.0.0: {} + p-reduce@3.0.0: {} p-retry@5.1.1: @@ -37620,7 +37678,7 @@ snapshots: debug: 4.3.4(supports-color@9.2.3) fault: 2.0.1 glob: 8.1.0 - ignore: 5.2.4 + ignore: 5.3.1 is-buffer: 2.0.5 is-empty: 1.2.0 is-plain-obj: 4.1.0