Skip to content

Commit

Permalink
chore: reproduced issue prisma/prisma#14043
Browse files Browse the repository at this point in the history
  • Loading branch information
jkomyno committed Jul 1, 2022
1 parent 0c76b4e commit a7189a8
Show file tree
Hide file tree
Showing 14 changed files with 664 additions and 462 deletions.
7 changes: 7 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
**/node_modules
**/lib
**/coverage
**/*.env
**/*.env.example
**/Dockerfile*
.gitattributes
10 changes: 7 additions & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
docker_base: ["alpine", "slim"]

name: "Docker: ${{ matrix.os }}"
name: "Docker: ${{ matrix.docker_base }}"

env:
DOCKER_BUILDKIT: 1
Expand All @@ -34,8 +35,11 @@ jobs:
restore-keys: |
${{ runner.os }}-
- name: Build Docker pnpm image
run: docker build -f Dockerfile.pnpm ./packages -t pnpm
- name: Build Docker jkomyno-pnpm image from ${{ matrix.docker_base }} Docker base image
run: docker build --build-arg DOCKER_BASE_IMAGE=${{ matrix.docker_base }} -f Dockerfile.pnpm . -t jkomyno-pnpm

- name: Build Docker jkomyno-example image
run: docker build -f ./packages/example/Dockerfile ./packages -t jkomyno-example

build:
runs-on: ${{ matrix.os }}
Expand Down
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
enable-pre-post-scripts=true
unsafe-perm=true
22 changes: 19 additions & 3 deletions Dockerfile.pnpm
Original file line number Diff line number Diff line change
@@ -1,18 +1,34 @@
ARG DOCKER_BASE_IMAGE="alpine"
ARG NODE_VERSION="18.0.0"
ARG PNPM_VERSION="6.32.3"

FROM node:${NODE_VERSION}-alpine as base-alpine
ENV IS_ALPINE=TRUE
ENV INSTALL_CMD="apk add --no-cache --upgrade git grep openssl openssl-dev gcompat libc6-compat"

FROM node:${NODE_VERSION}-slim as base-slim
ENV IS_ALPINE=FALSE
ENV INSTALL_CMD="apt-get update -y && \
apt-get install -y --upgrade git grep openssl"

##
# Create base image with pnpm installed
##

FROM node:${NODE_VERSION}-alpine as jkomyno-pnpm
FROM base-${DOCKER_BASE_IMAGE} as jkomyno-pnpm
LABEL jkomyno/pnpm-monorepo-example.name=pnpm

RUN apk add git
RUN apk add --no-cache --upgrade grep
# for alpine
RUN eval $INSTALL_CMD

RUN --mount=type=cache,id=pnpm-store,target=/root/.pnpm-store \
npm i -g pnpm@${PNPM_VERSION}

WORKDIR /app

COPY ["./*.json", "./*.yaml", "./"]

# enable pre/post hooks
COPY ["./.npmrc", "./.npmrc"]

RUN mkdir ./packages
42 changes: 22 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,33 @@

## What's Included

- `pnpm` workspace, whose configuration is stored in [`pnpm-workspace.yaml`](/pnpm-workspace.yaml). Two example packages are included, [`common-utils`](packages/common-utils) and [`example`](packages/example), with the latter importing `common-utils` as a dependency. All local packages are decorated with a `@jkomyno/*` scope (you may want to substitute these instances in the `name` entries of any `package.json` with yours or your company's name).
- `pnpm` workspace, whose configuration is stored in [`pnpm-workspace.yaml`](/pnpm-workspace.yaml). Two example packages are included, [`common-utils`](packages/common-utils) and [`example`](packages/example), with the latter importing `common-utils` as a dependency, as well as `prisma`. All local packages are decorated with a `@jkomyno/*` scope (you may want to substitute these instances in the `name` entries of any `package.json` with yours or your company's name).
- `turborepo`, whose configuration is stored in [`turbo.json`](./turbo.json)
- an example [`Dockerfile`](./Dockerfile.pnpm) that can be built and used as a base image for your Node.js Docker containers.
- the `jest` test engine, whose configuration is stored in the [`packages/jest`](./packages/jest) folder.
- opinionated [`prettier`](https://prettier.io) and [`eslint`](https://eslint.org) setups.

## How to build, test, and run with Docker

Ensure you have `Docker 20.10.5` installed and running with `docker -v`.
Build the `jkomyno-example` Docker image, which wraps `Node.js 18.0.0` on Linux Alpine with `pnpm 6.32.2` and `git`:

```bash
docker build -f Dockerfile.pnpm . -t jkomyno-pnpm
```

Build and run unit tests of [`example`](packages/example) with:

```bash
docker build -f ./packages/example/Dockerfile ./packages -t jkomyno-example
```

Run [`example`](packages/example) with:

```bash
docker run --rm -it jkomyno-example
```

## Available Scripts

- `pnpm install`: install the dependencies needed for each package.
Expand All @@ -24,25 +45,6 @@
- `pnpm test:unit`: run unit tests.
- `pnpm test:integration`: run integration tests.

## Test Structure

We follow an opinionated convention for storing an running tests.
All tests should be written in the `__tests__` directory of a local package.
Moreover, unit tests should be placed in the `__tests__/unit` folder; similarly, integration tests should be placed in the `__tests__/integration` folder.
This allows for easily running groups of tests (for instance, you might want to run unit tests locally, while deferring integration tests - that will probably need access to external services like Docker containers - to the CI only).

In each local package's `package.json` file, make sure to replace the `JEST_LIB_UNDER_TEST` environment variable declaration with the local package name, for each `test*` command in the `scripts` section.

## FAQ

1. How do I add a new package to the local workspace?

- Create a new folder `$packageName` in [`packages/`](packages/). Initialize it with a `tsconfig.json` file (which will reference the [`tsconfig.base.node.json`](./tsconfig.base.node.json) file at the root level) and a `package.json` file similarly to how it's done in the [`common-utils`](packages/common-utils) package.

2. How do I add a new depedency that should be available to each package in the local workspace?

> `pnpm add -w $dependencyName`
## 👤 Author

Hi, I'm **Alberto Schiabel**, you can follow me on:
Expand Down
14 changes: 8 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"pnpm": ">=6"
},
"scripts": {
"clean": "turbo run clean",
"clean:deep": "turbo run clean:deep",
"build": "turbo run build",
"watch": "turbo run watch",
"prettier-check": "turbo run prettier-check",
Expand All @@ -19,21 +21,21 @@
"test:ci": "turbo run test:ci"
},
"devDependencies": {
"@types/jest": "^27.4.1",
"@types/node": "^17.0.30",
"@types/jest": "^28.1.3",
"@types/node": "^18.0.0",
"@typescript-eslint/eslint-plugin": "^5.21.0",
"@typescript-eslint/parser": "^5.21.0",
"eslint": "^8.14.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jest": "^26.1.5",
"husky": "^7.0.4",
"jest": "^28.0.3",
"jest": "^28.1.1",
"prettier": "^2.6.2",
"rimraf": "^3.0.2",
"ts-jest": "28.0.0-next.3",
"turbo": "^1.2.6",
"typescript": "^4.6.4"
"ts-jest": "28.0.5",
"turbo": "^1.3.1",
"typescript": "^4.7.4"
},
"packageManager": "pnpm@6.32.3"
}
1 change: 1 addition & 0 deletions packages/common-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"main": "lib",
"scripts": {
"clean": "rimraf lib",
"clean:deep": "rimraf lib node_modules .turbo",
"build": "pnpm clean && tsc",
"prettier-check": "prettier --parser=typescript \"src/**/*.{js,ts}\" --check",
"prettier-write": "prettier --parser=typescript \"src/**/*.{js,ts}\" --write",
Expand Down
3 changes: 3 additions & 0 deletions packages/example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
# Keep environment variables out of version control
.env
55 changes: 55 additions & 0 deletions packages/example/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
##
# Install dependencies, generate Prisma client, transpile TypeScript to JavaScript,
# run unit tests, delete node_modules and source files
##

FROM jkomyno-pnpm AS builder
LABEL jkomyno/reproduce-issue-14043.name=example
LABEL jkomyno/reproduce-issue-14043.intermediate=true

WORKDIR /app/packages

# add test config
COPY ["./jest/", "./jest/"]

# add local dependency source
COPY ["./common-utils/", "./common-utils/"]

# add package itself
COPY ["./example/", "./example/"]

WORKDIR /app

# install
RUN --mount=type=cache,id=pnpm-store,target=/root/.pnpm-store \
pnpm install --frozen-lockfile \
| grep -v "cross-device link not permitted\|Falling back to copying packages from store"

RUN pnpm --filter "example" postinstall
RUN pnpm build
RUN pnpm --filter "example" test:unit
RUN rm -rf node_modules \
&& pnpm -r exec -- rm -rf node_modules src __tests__ jest

##
# Copy production dependencies and transpiled bundle, start application
##

FROM jkomyno-pnpm AS example
LABEL jkomyno/reproduce-issue-14043.name=example
LABEL jkomyno/reproduce-issue-14043.intermediate=false
WORKDIR /app

ENV NODE_ENV=production

COPY --from=builder /app .
RUN --mount=type=cache,id=pnpm-store,target=/root/.pnpm-store \
pnpm install --frozen-lockfile --prod \
| grep -v "cross-device link not permitted\|Falling back to copying packages from store"

WORKDIR /app/packages/example

# generate Prisma client
RUN pnpx prisma generate

ENTRYPOINT ["node", "lib"]
8 changes: 6 additions & 2 deletions packages/example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,19 @@
"main": "lib",
"scripts": {
"clean": "rimraf lib",
"clean:deep": "rimraf lib node_modules .turbo",
"build": "pnpm clean && tsc",
"prettier-check": "prettier --parser=typescript \"src/**/*.{js,ts}\" --check",
"prettier-write": "prettier --parser=typescript \"src/**/*.{js,ts}\" --write",
"typecheck": "tsc",
"eslint-check": "eslint \"src/**/*.{js,ts}\"",
"lint-staged": "lint-staged",
"pretest": "jest --clearCache"
"pretest": "jest --clearCache",
"postinstall": "prisma generate"
},
"dependencies": {
"@jkomyno/common-utils": "workspace:*"
"@jkomyno/common-utils": "workspace:*",
"prisma": "^4.0.0",
"@prisma/client": "^4.0.0"
}
}
28 changes: 28 additions & 0 deletions packages/example/prisma/schema.prisma
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
provider = "prisma-client-js"
output = "../node_modules/.prisma/client"
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

enum LogSeverity {
error
info
warn
}

model Log {
id String @id @default(uuid())
app String
timestamp Int
text String
severity LogSeverity @default(info)
created_at DateTime @db.Timestamptz(6) @default(now())
updated_at DateTime @db.Timestamptz(6) @default(now()) @updatedAt
}
3 changes: 3 additions & 0 deletions packages/example/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { PrismaClient } from '@prisma/client'
import { sum } from '@jkomyno/common-utils'

function main() {
const prisma = new PrismaClient()

const arr = [1, 2, 3]
console.log(`Summing ${arr.join(', ')} results in ${sum(arr)}`)
}
Expand Down

0 comments on commit a7189a8

Please sign in to comment.