Итак, у меня есть монорепозиторий NodeJS, который структурирован следующим образом:
monorepo/
├─ src/
│ ├─ libs/
│ │ ├─ types/
│ │ │ ├─ src/
│ │ │ ├─ package.json
│ ├─ some_app/
│ ├─ gcp_function/
│ │ ├─ src/
│ │ ├─ package.json
├─ package.json
В нескольких проектах используется одна и та же библиотека типов, поэтому в любое время при изменении типа мы можем обновить все ссылки одновременно. До сих пор это работало очень хорошо, и я очень доволен структурой.
За исключением того, что сейчас мне нужно было создать функцию на облачной платформе Google. В этой функции я также ссылаюсь на проект типов.
Функции package.json
следующие:
{
"devDependencies": {
"@project_name/types": "*",
"npm-watch": "^0.11.0",
"typescript": "^4.9.4"
}
}
@project_name/types
относится к проекту src/libs/types
. Это работает с каждым проектом, потому что у нас есть централизованный инструмент сборки.
Это означает, что функция работает локально на моем компьютере, и у меня нет проблем с ее разработкой, но как только я отправляю ее в Google Cloud (используя команду, указанную ниже), я получаю следующую ошибку:
npm ERR! 404 '@project_name/types@*' is not in this registry.
Я использую эту команду для развертывания из ./monorepo
:
gcloud functions deploy gcp-function --gen2 --runtime nodejs16 --trigger-topic some_topic --source .\src\gcp_function
Я думаю, довольно ясно, почему это происходит:
Google Cloud только продвигает функцию, которая затем строится на Google Cloud Build. Но поскольку остальная часть монорепозитория не загружается, она не работает, так как не имеет ссылки на @project_name/types
.
Я довольно долго боролся с этой проблемой. Кто-нибудь когда-нибудь сталкивался с этой проблемой, и если да, то как вы ее исправили? Есть ли другой способ использовать локальные зависимости для функций Google Cloud? Может быть, есть способ упаковать весь проект и отправить его в Google Cloud?
Я решил эту проблему, используя хитрость в конвейере CI.
В CI я делаю следующие шаги:
npm pack
, чтобы упаковать их.npm i @project_name/types@file:./types.tgz
. Таким образом, он переопределяется в package.json
.В итоге мой CI выглядит примерно так:
steps:
- name: Build types library
working-directory: ./src/libs/types
run: npm i --ignore-scripts && npm run build && npm pack
- name: Copy pack to gcp_function and install
run: cp ../libs/types/*.tgz ./types.tgz && npm i @project_name/types@file:./types.tgz
- name: Zip the current folder
run: rm -rf node_modules && zip -r function.zip ./
- name: Upload the function.zip to Google Cloud Storage
run: gsutil cp function.zip gs://some-bucket/gcp_function/function.zip
- name: Deploy to Google Cloud
run: |
gcloud functions deploy gcp_function \
--source gs://some-bucket/gcp_function/function.zip
Это решило проблему для меня. Теперь мне не нужно публиковать пакет в NPM (я не хотел этого делать, потому что это не вписывается в повествование о монорепозитории). И я все еще могу разрабатывать типы, которые обновляются в любом другом проекте во время разработки.