Skip to content

Commit

Permalink
revert(root): PR #6754 (#6856)
Browse files Browse the repository at this point in the history
  • Loading branch information
merrcury authored Nov 5, 2024
1 parent e5b4c69 commit 0999d22
Show file tree
Hide file tree
Showing 34 changed files with 990 additions and 1,397 deletions.
44 changes: 0 additions & 44 deletions apps/api/.dockerignore

This file was deleted.

74 changes: 46 additions & 28 deletions apps/api/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,54 +1,72 @@
# Use the base image for development
FROM ghcr.io/novuhq/novu/base:1.0.0 AS dev
FROM node:20-alpine3.19 AS dev_base
RUN apk add g++ make py3-pip

ENV NX_DAEMON=false

RUN npm i pm2 -g
RUN npm --no-update-notifier --no-fund --global install [email protected]
RUN pnpm --version

USER 1000
WORKDIR /usr/src/app

# ------- DEV BUILD ----------
FROM dev_base AS dev
ARG PACKAGE_PATH

# Copy necessary directories to the image
COPY --chown=1000:1000 ./meta ./deps ./pkg ./
COPY --chown=1000:1000 ./meta .
COPY --chown=1000:1000 ./deps .
COPY --chown=1000:1000 ./pkg .

RUN --mount=type=secret,id=BULL_MQ_PRO_NPM_TOKEN,uid=1000 export BULL_MQ_PRO_NPM_TOKEN=$(cat /run/secrets/BULL_MQ_PRO_NPM_TOKEN) && \
if [ -n "${BULL_MQ_PRO_NPM_TOKEN}" ] ; then echo 'Building with Enterprise Edition of Novu'; rm -f .npmrc ; cp .npmrc-cloud .npmrc ; fi

RUN --mount=type=cache,id=pnpm-store-api,target=/root/.pnpm-store\
--mount=type=secret,id=BULL_MQ_PRO_NPM_TOKEN,uid=1000 export BULL_MQ_PRO_NPM_TOKEN=$(cat /run/secrets/BULL_MQ_PRO_NPM_TOKEN) && \
pnpm install --filter "novuhq" --filter "{${PACKAGE_PATH}}..."\
--frozen-lockfile\
--unsafe-perm

# Install dependencies and build the project
RUN --mount=type=secret,id=BULL_MQ_PRO_NPM_TOKEN,uid=1000 \
BULL_MQ_PRO_NPM_TOKEN=$(cat /run/secrets/BULL_MQ_PRO_NPM_TOKEN) && \
[ -n "$BULL_MQ_PRO_NPM_TOKEN" ] && echo 'Building with Enterprise Edition of Novu' && \
rm -f .npmrc && cp .npmrc-cloud .npmrc || true && \
pnpm install --filter "novuhq" --filter "{${PACKAGE_PATH}}..." --frozen-lockfile --unsafe-perm && \
NODE_ENV=production NX_DAEMON=false pnpm build:api
RUN --mount=type=secret,id=BULL_MQ_PRO_NPM_TOKEN,uid=1000 export BULL_MQ_PRO_NPM_TOKEN=$(cat /run/secrets/BULL_MQ_PRO_NPM_TOKEN) && NODE_ENV=production NX_DAEMON=false pnpm build:api

# Set the working directory to the API app and copy example environment file
WORKDIR /usr/src/app/apps/api

RUN cp src/.example.env dist/.env
RUN cp src/.env.test dist/.env.test
RUN cp src/.env.development dist/.env.development
RUN cp src/.env.production dist/.env.production

# Set the working directory to the root of the app
WORKDIR /usr/src/app

# ------- ASSETS BUILD ----------
# Create a new stage for building assets
FROM dev AS assets

# Remove node_modules and source directories
WORKDIR /usr/src/app

# Remove all dependencies so later we can only install prod dependencies without devDependencies
RUN rm -rf node_modules && pnpm recursive exec -- rm -rf ./src ./node_modules

# ------- PRODUCTION BUILD ----------
# Use the base image for production
FROM ghcr.io/novuhq/novu/base:1.0.0 AS prod
FROM dev_base AS prod

ARG PACKAGE_PATH

# Set environment variables for production
ENV CI=true
ENV NEW_RELIC_NO_CONFIG_FILE=true

# Set the working directory to the root of the app
WORKDIR /usr/src/app

# Copy necessary directories from the build stage
COPY --chown=1000:1000 ./meta ./
COPY --chown=1000:1000 ./meta .

# Get the build artifacts that only include dist folders
COPY --chown=1000:1000 --from=assets /usr/src/app .

# Install production dependencies
RUN --mount=type=cache,id=pnpm-store-api,target=/root/.pnpm-store \
--mount=type=secret,id=BULL_MQ_PRO_NPM_TOKEN,uid=1000 \
pnpm install --filter "{${PACKAGE_PATH}}..." --frozen-lockfile --unsafe-perm --prod
RUN --mount=type=cache,id=pnpm-store-api,target=/root/.pnpm-store\
--mount=type=secret,id=BULL_MQ_PRO_NPM_TOKEN,uid=1000 export BULL_MQ_PRO_NPM_TOKEN=$(cat /run/secrets/BULL_MQ_PRO_NPM_TOKEN) && \
pnpm install --filter "{${PACKAGE_PATH}}..." \
--frozen-lockfile \
--unsafe-perm

ENV NEW_RELIC_NO_CONFIG_FILE=true

# Set the working directory to the API app and start the application using pm2-runtime
WORKDIR /usr/src/app/apps/api
CMD [ "pm2-runtime", "start", "dist/main.js" ]
CMD [ "pm2-runtime","start", "dist/main.js" ]
63 changes: 31 additions & 32 deletions apps/api/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,50 @@
/* eslint-disable global-require */
import { DynamicModule, Logger, Module, Provider } from '@nestjs/common';
import { ForwardReference } from '@nestjs/common/interfaces/modules/forward-reference.interface';
import { Type } from '@nestjs/common/interfaces/type.interface';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { GracefulShutdownConfigModule, ProfilingModule, TracingModule } from '@novu/application-generic';
import { Type } from '@nestjs/common/interfaces/type.interface';
import { ForwardReference } from '@nestjs/common/interfaces/modules/forward-reference.interface';
import { ProfilingModule, TracingModule } from '@novu/application-generic';
import { isClerkEnabled } from '@novu/shared';
import { SentryModule } from '@sentry/nestjs/setup';
import packageJson from '../package.json';
import { AnalyticsModule } from './app/analytics/analytics.module';
import { SharedModule } from './app/shared/shared.module';
import { UserModule } from './app/user/user.module';
import { AuthModule } from './app/auth/auth.module';
import { BlueprintModule } from './app/blueprint/blueprint.module';
import { BridgeModule } from './app/bridge/bridge.module';
import { ChangeModule } from './app/change/change.module';
import { ContentTemplatesModule } from './app/content-templates/content-templates.module';
import { EnvironmentsModuleV1 } from './app/environments-v1/environments-v1.module';
import { EnvironmentsModule } from './app/environments-v2/environments.module';
import { EventsModule } from './app/events/events.module';
import { ExecutionDetailsModule } from './app/execution-details/execution-details.module';
import { FeedsModule } from './app/feeds/feeds.module';
import { TestingModule } from './app/testing/testing.module';
import { HealthModule } from './app/health/health.module';
import { InboundParseModule } from './app/inbound-parse/inbound-parse.module';
import { InboxModule } from './app/inbox/inbox.module';
import { IntegrationModule } from './app/integrations/integrations.module';
import { OrganizationModule } from './app/organization/organization.module';
import { ExecutionDetailsModule } from './app/execution-details/execution-details.module';
import { EventsModule } from './app/events/events.module';
import { WidgetsModule } from './app/widgets/widgets.module';
import { NotificationModule } from './app/notifications/notification.module';
import { StorageModule } from './app/storage/storage.module';
import { NotificationGroupsModule } from './app/notification-groups/notification-groups.module';
import { InvitesModule } from './app/invites/invites.module';
import { ContentTemplatesModule } from './app/content-templates/content-templates.module';
import { IntegrationModule } from './app/integrations/integrations.module';
import { ChangeModule } from './app/change/change.module';
import { SubscribersModule } from './app/subscribers/subscribers.module';
import { FeedsModule } from './app/feeds/feeds.module';
import { LayoutsModule } from './app/layouts/layouts.module';
import { MessagesModule } from './app/messages/messages.module';
import { NotificationGroupsModule } from './app/notification-groups/notification-groups.module';
import { NotificationModule } from './app/notifications/notification.module';
import { OrganizationModule } from './app/organization/organization.module';
import { PartnerIntegrationsModule } from './app/partner-integrations/partner-integrations.module';
import { PreferencesModule } from './app/preferences';
import { TopicsModule } from './app/topics/topics.module';
import { InboundParseModule } from './app/inbound-parse/inbound-parse.module';
import { BlueprintModule } from './app/blueprint/blueprint.module';
import { TenantModule } from './app/tenant/tenant.module';
import { IdempotencyInterceptor } from './app/shared/framework/idempotency.interceptor';
import { WorkflowOverridesModule } from './app/workflow-overrides/workflow-overrides.module';
import { ApiRateLimitInterceptor } from './app/rate-limiting/guards';
import { RateLimitingModule } from './app/rate-limiting/rate-limiting.module';
import { IdempotencyInterceptor } from './app/shared/framework/idempotency.interceptor';
import { ProductFeatureInterceptor } from './app/shared/interceptors/product-feature.interceptor';
import { SharedModule } from './app/shared/shared.module';
import { StorageModule } from './app/storage/storage.module';
import { SubscribersModule } from './app/subscribers/subscribers.module';
import { TenantModule } from './app/tenant/tenant.module';
import { TestingModule } from './app/testing/testing.module';
import { TopicsModule } from './app/topics/topics.module';
import { UserModule } from './app/user/user.module';
import { WidgetsModule } from './app/widgets/widgets.module';
import { WorkflowOverridesModule } from './app/workflow-overrides/workflow-overrides.module';
import { WorkflowModuleV1 } from './app/workflows-v1/workflow-v1.module';
import { AnalyticsModule } from './app/analytics/analytics.module';
import { InboxModule } from './app/inbox/inbox.module';
import { BridgeModule } from './app/bridge/bridge.module';
import { PreferencesModule } from './app/preferences';
import { WorkflowModule } from './app/workflows-v2/workflow.module';
import { WorkflowModuleV1 } from './app/workflows-v1/workflow-v1.module';
import { EnvironmentsModuleV1 } from './app/environments-v1/environments-v1.module';
import { EnvironmentsModule } from './app/environments-v2/environments.module';

const enterpriseImports = (): Array<Type | DynamicModule | Promise<DynamicModule> | ForwardReference> => {
const modules: Array<Type | DynamicModule | Promise<DynamicModule> | ForwardReference> = [];
Expand Down Expand Up @@ -106,7 +106,6 @@ const baseModules: Array<Type | DynamicModule | Promise<DynamicModule> | Forward
BridgeModule,
PreferencesModule,
WorkflowModule,
GracefulShutdownConfigModule.forRootAsync(),
EnvironmentsModule,
];

Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/app/environments-v1/novu-bridge.controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Controller, Req, Res, Inject, Get, Post, Options } from '@nestjs/common';
import type { Request, Response } from 'express';
import { Request, Response } from 'express';
import { ApiExcludeController } from '@nestjs/swagger';
import { NovuClient } from '@novu/framework/nest';
import { NovuBridgeClient } from './novu-bridge-client';
Expand Down
12 changes: 7 additions & 5 deletions apps/api/src/bootstrap.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import 'newrelic';
import './config/env.config';
import './instrument';
import 'newrelic';

import helmet from 'helmet';
import { INestApplication, Logger, ValidationPipe, VersioningType } from '@nestjs/common';
import { NestFactory, Reflector } from '@nestjs/core';
import bodyParser from 'body-parser';
import helmet from 'helmet';

import { ExpressAdapter } from '@nestjs/platform-express';
import { BullMqService, getErrorInterceptor, Logger as PinoLogger } from '@novu/application-generic';
import { ExpressAdapter } from '@nestjs/platform-express';
import { CONTEXT_PATH, corsOptionsDelegate, validateEnv } from './config';
import { AppModule } from './app.module';
import { setupSwagger } from './app/shared/framework/swagger/swagger.controller';
import { SubscriberRouteGuard } from './app/auth/framework/subscriber-route.guard';
import { ResponseInterceptor } from './app/shared/framework/response.interceptor';
import { setupSwagger } from './app/shared/framework/swagger/swagger.controller';
import { CONTEXT_PATH, corsOptionsDelegate, validateEnv } from './config';
import { AllExceptionsFilter } from './exception-filter';

const passport = require('passport');
Expand Down Expand Up @@ -108,6 +108,8 @@ export async function bootstrap(expressApp?): Promise<INestApplication> {
await app.listen(process.env.PORT);
}

app.enableShutdownHooks();

Logger.log(`Started application in NODE_ENV=${process.env.NODE_ENV} on port ${process.env.PORT}`);

return app;
Expand Down
1 change: 0 additions & 1 deletion apps/api/src/config/env.validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ export const envValidators = {
NOVU_INVITE_TEAM_MEMBER_NUDGE_TRIGGER_IDENTIFIER: str({ default: undefined }),
HUBSPOT_INVITE_NUDGE_EMAIL_USER_LIST_ID: str({ default: undefined }),
HUBSPOT_PRIVATE_APP_ACCESS_TOKEN: str({ default: undefined }),
GRACEFUL_SHUTDOWN_TIMEOUT: num({ default: 5000 }),
// Feature Flags
...Object.keys(FeatureFlagsKeysEnum).reduce(
(acc, key) => {
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/exception-filter.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ArgumentsHost, ExceptionFilter, HttpException, HttpStatus } from '@nestjs/common';
import type { Response, Request } from 'express';
import { Response } from 'express';
import { CommandValidationException, PinoLogger } from '@novu/application-generic';
import { randomUUID } from 'node:crypto';
import { captureException } from '@sentry/node';
Expand Down
44 changes: 0 additions & 44 deletions apps/webhook/.dockerignore

This file was deleted.

Loading

0 comments on commit 0999d22

Please sign in to comment.