prisma / prisma

Next-generation ORM for Node.js & TypeScript | PostgreSQL, MySQL, MariaDB, SQL Server, SQLite, MongoDB and CockroachDB
https://www.prisma.io
Apache License 2.0
39.88k stars 1.56k forks source link

prisma migrate deploy fails in gitlab and azure cicd (v2.20.1) #6385

Closed kokokenada closed 3 years ago

kokokenada commented 3 years ago

Bug description

prisma migrate deploy causes:

Error: Cannot find module '/root/.npm/_npx/489/lib/node_modules/prisma/scripts/preinstall-entry.js'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:831:15)
    at Function.Module._load (internal/modules/cjs/loader.js:687:27)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
    at internal/main/run_main_module.js:17:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! prisma@2.20.1 preinstall: `node scripts/preinstall-entry.js`
npm ERR! Exit status 1
npm ERR! 

How to reproduce

Running 'npx prisma migrate deploy' from the .gitlab-ci.yml encounters the error above .npmrc has unsafe-perm=true which was required to fix npx prisma generate

Prisma information

Environment & setup

prisma@2.20.1

janpio commented 3 years ago

Is Prisma already installed before executing this command as a local dependency of the project or do you think the command itself downloads and installs the Prisma CLI?

kokokenada commented 3 years ago

npm install was run prior to the error, npm generate also run successfully prior to the error. (Until I added .npmrc with unsafe-perm=true, the error occurred at the prior npm generate step. Adding the .npmrc file advanced the process, but it still crashes at the migrate deploy stage.

kokokenada commented 3 years ago

I seem to have been able to work around this problem by downgrading to 2.16.1

pantharshit00 commented 3 years ago

Can you share your gitlab ci config file?

kokokenada commented 3 years ago

Sure. Here; you go:

image: node:12.19 # lambci/lambda:nodejs12.x

stages:
  - build_backend
  - pages

cloud_server_build:
  stage: build_backend
  tags:
    - alibitech
  before_script:
    - echo 'before_script cloud_server_build started'
    - npm config set prefix /usr/local
    - npm install
  script:
    - cd packages/back-end
    - export start=$SECONDS
    - echo 'npm install started'
    - npm install
    - npm run copy-lib
    - export duration=$(( $SECONDS - $start))
    - echo "npm Duration = $duration"
    - export start=$SECONDS
    - echo 'build cli'
    - npm run build-cli
    - export duration=$(( $SECONDS - $start))
    - echo "npm cli build = $duration"
    - export start=$SECONDS
    - echo 'set-env'
    - . ./set-env.sh
    - export duration=$(( $SECONDS - $start))
    - echo "set env = $duration"
    - export start=$SECONDS
    - echo 'script migrate_db started'
    - ./db-deploy.sh
    - export duration=$(( $SECONDS - $start))
    - echo "db-deploy.sh Duration = $duration"
    - export start=$SECONDS
    - ./compile.sh
    - export duration=$(( $SECONDS - $start))
    - echo "Compile Duration = $duration"
    - export start=$SECONDS
    - ./deploy-brand.sh
    - export duration=$(( $SECONDS - $start))
    - echo "Deploy Duration = $duration"
    - export start=$SECONDS
    - npm run config-shopify
    - export duration=$(( $SECONDS - $start))
    - echo "Shopify Config Duration = $duration"
    - export start=$SECONDS
    - cd ../fusion-auth
    - npm install
    - npm run copy-lib
    - npm run config
    - export duration=$(( $SECONDS - $start))
    - echo "Fusion Auth Config Duration = $duration"
  environment: $CI_COMMIT_BRANCH
#  cache:
#    paths:
#      - packages/back-end/node_modules
#  artifacts:
#    paths:
#      - packages/back-end
#    expire_in: 3 days

# https://github.com/gatsbyjs/gatsby/commit/c08fa4a6a6a7e8cc7e06ed4e28a8e325fbf96412
# https://github.com/gatsbyjs/gatsby/pull/24535

ssg_build:
  stage: pages
  tags:
    - alibitech
  variables:
    GATSBY_EXPERIMENTAL_PAGE_BUILD_ON_DATA_CHANGES: 'true'
    CONNECTION_TIMEOUT: 90000
    GATSBY_CONNECTION_TIMEOUT: 90000
    STALL_TIMEOUT: 90000
    GATSBY_STALL_TIMEOUT: 90000
    STALL_RETRY_LIMIT: 10
    GATSBY_STALL_RETRY_LIMIT: 10
    GATSBY_CONCURRENT_DOWNLOAD: 10
  before_script:
    - echo 'before_script cloud_deploy started'
    - export start=$SECONDS
    - npm config set prefix /usr/local
    # - npm install -g serverless
    # - export duration=$(( $SECONDS - $start))
    # - echo "npm install serverless globally = $duration"
    # - export start=$SECONDS
    - cd packages/back-end
    - npm ci --cache .npm --prefer-offline
    - npm install
    - npm run copy-lib
    - export duration=$(( $SECONDS - $start))
    - echo "npm install in back-end = $duration"
    - export start=$SECONDS
    - echo 'build cli'
    - npm run build-cli
    - export duration=$(( $SECONDS - $start))
    - echo "npm cli build = $duration"
    - cd ../..
    - . ./set-env.sh
    - export start=$SECONDS
    - cd packages/contentful
    - npm install
    - cd contentful-export
    - npm install
    - npm run build
    - cd ../contentful-import
    - npm install
    - npm run build
    - cd ..
    - ./migrate.sh $GATSBY_BRAND_ID
    - export duration=$(( $SECONDS - $start))
    - echo "migration duration = $duration"
    - export start=$SECONDS
    - echo "building widget"
    - cd ../widget-lib
    - npm install
    - npm run build
    - echo "widget build done = $duration"
    - export start=$SECONDS
    - cd ../ui
    - npm ci --cache .npm --prefer-offline
    - npm install
    - npm run copy-lib
    - export duration=$(( $SECONDS - $start))
    - echo "npm install in ui = $duration"
  script:
    - export start=$SECONDS
    - npm run build
    - export duration=$(( $SECONDS - $start))
    - echo "build ui = $duration"
    - export start=$SECONDS
    - npm run test
    - export duration=$(( $SECONDS - $start))
    - echo "test ui = $duration"
    - export start=$SECONDS
    - npm run deploy
    # - sls client deploy --no-confirm
    - export duration=$(( $SECONDS - $start))
    - echo "deploy ui = $duration"
    - export start=$SECONDS
    # pvep json-prod-to-db take json file that's in the source, and copy it to database
    - pvep --sync-shopify -b $GATSBY_BRAND_ID
    - export duration=$(( $SECONDS - $start))
    - echo "sync shopify products = $duration"
    - export start=$SECONDS
    - pvep --invalidate-cache
    - export duration=$(( $SECONDS - $start))
    - echo "invalidate cache = $duration"
    - cd ../..
  cache:
    key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG-v2"
    paths:
      - .npm/
      - .cache/
      - packages/ui/.npm/
      - packages/back-end/.npm/
      - packages/ui/.cache
      - packages/ui/public
  environment:
    name: review/$CI_COMMIT_REF_NAME
    url: http://$CI_COMMIT_REF_NAME-ui-pvep.s3-website-us-east-1.amazonaws.com/app
  needs: []

#pages:
#  stage: pages
#  script:
#    - yarn
#    - ./build.sh
#  artifacts:
#    paths:
#      - packages/ui/public

On it's own, it does't paint the full picture, so here's some scripts it calls:

npm run build-cli does 'rm -rf ./cli-build; npx prisma generate; tsc --build tsconfig-cli.json; npm install -g'

db-deploy.sh is: (the reason for the retries is sometimes Aurora serverless needs to wake up, if I recall correctly.

#!/bin/bash

#will exit if any of the commands fail
set -e

echo "db-deploy.sh: running 'npx prisma migrate deploy' to install tables"
echo "POSTGRES_USER=$POSTGRES_USER POSTGRES_SERVER=$POSTGRES_SERVER POSTGRES_PORT=$POSTGRES_PORT"
n=0
until [ "$n" -ge 5 ]
do
   npx prisma migrate deploy --preview-feature && break  # substitute your command here
   n=$((n+1))
   sleep 30
done
if [ "$n" == "5" ]; then
  echo "Migration failed after many retries"
  exit 1
fi
echo "db-deploy.sh: 'npx prisma migrate deploy' completed OK"
echo "db-deploy.sh: running 'npx prisma db seed' to install seed data"
npx prisma db seed --preview-feature
echo "db-deploy.sh: 'npx prisma db seed' completed OK"
Jolg42 commented 3 years ago

Error: Cannot find module '/root/.npm/_npx/489/lib/node_modules/prisma/scripts/preinstall-entry.js' and npm run copy-lib is making me think that you are copying something, maybe node_modules/prisma somewhere?

Note: npx prisma@2.20.1 -v works fine

kokokenada commented 3 years ago

This exact same problem popped up again on a completely different project (trying to upgrade to 2.21.2) this time in Azure:

Step 4/18 : RUN yarn install
 ---> Running in f71e698b77f9
yarn install v1.22.4
[1/4] Resolving packages...
[2/4] Fetching packages...
info fsevents@1.2.12: The platform "linux" is incompatible with this module.
info "fsevents@1.2.12" is an optional dependency and failed compatibility check. Excluding it from installation.
info fsevents@2.1.3: The platform "linux" is incompatible with this module.
info "fsevents@2.1.3" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
warning " > @typescript-eslint/eslint-plugin@2.30.0" has unmet peer dependency "eslint@^5.0.0 || ^6.0.0".
warning "@typescript-eslint/eslint-plugin > @typescript-eslint/experimental-utils@2.30.0" has unmet peer dependency "eslint@*".
warning " > @typescript-eslint/parser@2.30.0" has unmet peer dependency "eslint@^5.0.0 || ^6.0.0".
warning " > babel-loader@8.1.0" has unmet peer dependency "webpack@>=2".
warning " > ts-jest@26.1.0" has incorrect peer dependency "typescript@>=3.8 <4.0".
[4/4] Building fresh packages...
Done in 33.15s.
Removing intermediate container f71e698b77f9
 ---> 5fcc2ee1dae5
Step 5/18 : RUN yarn build
 ---> Running in cba740949291
yarn run v1.22.4
$ npx prisma generate; tsc
internal/modules/cjs/loader.js:968
  throw err;
  ^

Error: Cannot find module '/root/.npm/_npx/29/lib/node_modules/prisma/scripts/preinstall-entry.js'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:965:15)
    at Function.Module._load (internal/modules/cjs/loader.js:841:27)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
    at internal/main/run_main_module.js:17:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}

All these problems stem from the dubious behavior of writing application data into node_modules. Any plans to change this or give an option to change write the prisma client so it can be checked in to git to avoid all these CICD headaches?

janpio commented 3 years ago

or give an option to change write the prisma client so it can be checked in to git to avoid all these CICD headaches?

We got you: https://www.prisma.io/docs/concepts/components/prisma-client/working-with-prismaclient/generating-prisma-client#using-a-custom-output-path

kokokenada commented 3 years ago

That might useful. I did give it a try, but it was not a simple work around to my problem. It also generates the binaries which I didn't want to check in, so I would have to run prisma generate - so it would just be kicking the can down the road. I also had trouble easily transitioning on my local build. I attempted to do so by adding paths: {"@prisma/client": ["where it was generated"]} to my tsconfig.json to avoid changing all the imports - but the client was not imported into the build.

In search of a quick fix, I downgraded and my build sprang to life again. 2.17.0, 2.18.0 and 2.19.0 all worked. 2.20.1 failed. So something in prisma has changed in 2.20.1 that is breaking my build. Just to provide a few more details about the problem, after doing yarn install, tsc is used to complete the build. When I attempted an upgrade to 2.21.2, it could not find any of the generated prisma files. "No problem", I thought, I'll just add an npx prisma generate. And that's where the "Error: Cannot find module" occurs.

kokokenada commented 3 years ago

And in case the Dockerfile is helpful, here it is:

FROM node:12.18
WORKDIR /api
COPY ./ /api/
ENV NODE_PATH=/api/build/src
RUN yarn install
RUN yarn build
#Can be redefined during deploy
ENV CSA_API_PORT=7071
EXPOSE 7071
CMD node build/src/graphql-server.js
pantharshit00 commented 3 years ago

I am unable to reproduce this on Azure :|

Are you using a monorepo setup by any chance?

kokokenada commented 3 years ago

Thanks for the reply. It is a mono repo. The good news is that the problem has gone away with an upgrade to 2.22.1 (from 2.19.0). I didn't see anything in the release notes, and perhaps something else has changed, but I was finally able to upgrade.

Jolg42 commented 3 years ago

Happy it works! Closing then since it works with 2.22.1 👍