console/deployment/services/graphql.ts

235 lines
8.5 KiB
TypeScript
Raw Normal View History

2022-05-18 07:26:57 +00:00
import * as pulumi from '@pulumi/pulumi';
2022-12-28 19:22:54 +00:00
import { serviceLocalEndpoint } from '../utils/local-endpoint';
import { ServiceSecret } from '../utils/secrets';
2022-12-28 19:22:54 +00:00
import { ServiceDeployment } from '../utils/service-deployment';
import { CDN } from './cf-cdn';
2022-05-18 07:26:57 +00:00
import { Clickhouse } from './clickhouse';
import { CommerceService } from './commerce';
2022-12-28 19:22:54 +00:00
import { DbMigrations } from './db-migrations';
2024-03-04 12:56:12 +00:00
import { Docker } from './docker';
2022-12-28 19:22:54 +00:00
import { Emails } from './emails';
2024-03-04 12:56:12 +00:00
import { Environment } from './environment';
import { GitHubApp } from './github';
2024-04-07 08:57:03 +00:00
import { Observability } from './observability';
import { SchemaPolicy } from './policy';
2024-03-04 12:56:12 +00:00
import { Postgres } from './postgres';
2022-12-28 19:22:54 +00:00
import { Redis } from './redis';
2024-03-04 12:56:12 +00:00
import { S3 } from './s3';
2022-12-28 19:22:54 +00:00
import { Schema } from './schema';
2024-03-04 12:56:12 +00:00
import { Sentry } from './sentry';
import { Supertokens } from './supertokens';
2022-12-28 19:22:54 +00:00
import { Tokens } from './tokens';
2022-05-18 07:26:57 +00:00
import { Usage } from './usage';
2022-12-28 19:22:54 +00:00
import { Webhooks } from './webhooks';
2024-03-04 12:56:12 +00:00
import { Zendesk } from './zendesk';
2022-05-18 07:26:57 +00:00
export type GraphQL = ReturnType<typeof deployGraphQL>;
class AppOAuthSecret extends ServiceSecret<{
clientId: string | pulumi.Output<string>;
clientSecret: string | pulumi.Output<string>;
}> {}
2022-05-18 07:26:57 +00:00
export function deployGraphQL({
clickhouse,
image,
2024-03-04 12:56:12 +00:00
environment,
2022-05-18 07:26:57 +00:00
tokens,
webhooks,
schema,
schemaPolicy,
2022-11-07 13:27:19 +00:00
cdn,
2022-05-18 07:26:57 +00:00
redis,
usage,
commerce,
2022-05-18 07:26:57 +00:00
dbMigrations,
emails,
2024-03-04 12:56:12 +00:00
supertokens,
s3,
s3Mirror,
s3AuditLog,
2024-03-04 12:56:12 +00:00
zendesk,
docker,
postgres,
githubApp,
sentry,
2024-04-07 08:57:03 +00:00
observability,
2022-05-18 07:26:57 +00:00
}: {
2024-04-07 08:57:03 +00:00
observability: Observability;
2024-03-04 12:56:12 +00:00
githubApp: GitHubApp;
postgres: Postgres;
image: string;
2022-05-18 07:26:57 +00:00
clickhouse: Clickhouse;
2024-03-04 12:56:12 +00:00
environment: Environment;
2022-05-18 07:26:57 +00:00
tokens: Tokens;
webhooks: Webhooks;
schema: Schema;
schemaPolicy: SchemaPolicy;
2022-05-18 07:26:57 +00:00
redis: Redis;
2022-11-07 13:27:19 +00:00
cdn: CDN;
2024-03-04 12:56:12 +00:00
s3: S3;
s3Mirror: S3;
s3AuditLog: S3;
2022-05-18 07:26:57 +00:00
usage: Usage;
dbMigrations: DbMigrations;
commerce: CommerceService;
emails: Emails;
2024-03-04 12:56:12 +00:00
supertokens: Supertokens;
zendesk: Zendesk;
docker: Docker;
sentry: Sentry;
2022-05-18 07:26:57 +00:00
}) {
2024-03-04 12:56:12 +00:00
const apiConfig = new pulumi.Config('api');
const apiEnv = apiConfig.requireObject<Record<string, string>>('env');
feat: clean app env (#422) * feat: document environment variables * more env documentation * wip * add noop for backend env * typo * feat: embed environment validation/parsing in built app * fix the sentry integration 😌 * feat: use env * feat: decode the usage service environment * feat: decode the webhooks service environment * feat: disallow process.env * feat: decode the tokens service environment * feat: decode the stripe-billing service environment * feat: decode server service environment * feat: decode schema service environment * feat: decode rate-limit service environment * feat: decode usage-estimator service environment * feat: decode emails service environment * adjust env * remove commented out code * adjust env variable name * use separate env variables * env fixes * more environmental stuff :) * ... * replace POSTGRES_CONNECTION_STRING with specific environment variables * handle optional clickhouse (for now :) * add missing POSTGRES_DB environment variable * make ENVIRONMENT optional * the other matters lol * feat: support delivering mails via SMTP (#412) * feat: optional CDN (#410) * feat: optional CDN * enable CDN in deployment * enable the CDN in integration tests * add sendmail provider * remove unused env variables from the deployment * only show login alert when legacy auth0 migration is enabled * feat: make TOKENS_ENDPOINT mandatory and RATE_LIMIT_ENDPOINT optional for usage service * feat: upgrade supertokens and enable server side email confirmation (#423) * feat: upgrade supertokens and enable server side email confirmation * feat: opt into required email verification * docs: self hosting (#428) * docs: self-hosting quick start * Update packages/web/docs/pages/self-hosting/get-started.mdx Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> * feat: optional GitHub and Slack environment variables (#440) * feat: optional github integration environment variables * feat: optional slack integration (#441) * use latest stable supertokens Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
2022-10-04 12:30:21 +00:00
const hiveConfig = new pulumi.Config('hive');
const oauthConfig = new pulumi.Config('oauth');
const githubOAuthSecret = new AppOAuthSecret('oauth-github', {
clientId: oauthConfig.requireSecret('githubClient'),
clientSecret: oauthConfig.requireSecret('githubSecret'),
});
const googleOAuthSecret = new AppOAuthSecret('oauth-google', {
clientId: oauthConfig.requireSecret('googleClient'),
clientSecret: oauthConfig.requireSecret('googleSecret'),
});
const persistedDocumentsSecret = new ServiceSecret('persisted-documents', {
cdnAccessKeyId: apiConfig.requireSecret('hivePersistedDocumentsCdnAccessKeyId'),
});
const hiveUsageSecret = new ServiceSecret('hive-usage', {
usageAccessToken: hiveConfig.requireSecret('usageAccessToken'),
});
2024-03-04 12:56:12 +00:00
return (
new ServiceDeployment(
'graphql-api',
{
imagePullSecret: docker.secret,
image,
replicas: environment.podsConfig.general.replicas,
2024-03-04 12:56:12 +00:00
pdb: true,
readinessProbe: '/_readiness',
livenessProbe: '/_health',
startupProbe: {
endpoint: '/_health',
initialDelaySeconds: 60,
failureThreshold: 10,
periodSeconds: 15,
timeoutSeconds: 15,
},
availabilityOnEveryNode: true,
env: {
...environment.envVars,
...apiEnv,
SENTRY: sentry.enabled ? '1' : '0',
REQUEST_LOGGING: '1', // disabled
COMMERCE_ENDPOINT: serviceLocalEndpoint(commerce.service),
2024-03-04 12:56:12 +00:00
TOKENS_ENDPOINT: serviceLocalEndpoint(tokens.service),
SCHEMA_ENDPOINT: serviceLocalEndpoint(schema.service),
SCHEMA_POLICY_ENDPOINT: serviceLocalEndpoint(schemaPolicy.service),
WEB_APP_URL: `https://${environment.appDns}`,
GRAPHQL_PUBLIC_ORIGIN: `https://${environment.appDns}`,
2024-03-04 12:56:12 +00:00
CDN_CF: '1',
HIVE_USAGE: '1',
HIVE_TARGET: hiveConfig.require('target'),
HIVE_USAGE_ENDPOINT: serviceLocalEndpoint(usage.service),
HIVE_TRACING: '1',
HIVE_TRACING_ENDPOINT: environment.isProduction
? 'https://api.graphql-hive.com/otel/v1/traces'
: environment.isStaging
? 'https://api.hiveready.dev/otel/v1/traces'
: 'https://api.buzzcheck.dev/otel/v1/traces',
HIVE_PERSISTED_DOCUMENTS: '1',
2024-03-04 12:56:12 +00:00
ZENDESK_SUPPORT: zendesk.enabled ? '1' : '0',
INTEGRATION_GITHUB: '1',
// Auth
2024-03-04 12:56:12 +00:00
SUPERTOKENS_CONNECTION_URI: supertokens.localEndpoint,
AUTH_GITHUB: '1',
AUTH_GOOGLE: '1',
2024-03-04 12:56:12 +00:00
AUTH_ORGANIZATION_OIDC: '1',
AUTH_REQUIRE_EMAIL_VERIFICATION: '1',
2024-04-07 08:57:03 +00:00
// Traces (OTLP)
OPENTELEMETRY_COLLECTOR_ENDPOINT:
observability.enabled && observability.tracingEndpoint
? observability.tracingEndpoint
: '',
S3_MIRROR: '1',
2024-03-04 12:56:12 +00:00
},
exposesMetrics: true,
port: 4000,
},
2024-03-04 12:56:12 +00:00
[
dbMigrations,
redis.deployment,
redis.service,
clickhouse.deployment,
clickhouse.service,
commerce.deployment,
commerce.service,
2024-03-04 12:56:12 +00:00
],
)
// GitHub App
.withSecret('INTEGRATION_GITHUB_APP_ID', githubApp.secret, 'appId')
.withSecret('INTEGRATION_GITHUB_APP_PRIVATE_KEY', githubApp.secret, 'privateKey')
// Clickhouse
.withSecret('CLICKHOUSE_HOST', clickhouse.secret, 'host')
.withSecret('CLICKHOUSE_PORT', clickhouse.secret, 'port')
.withSecret('CLICKHOUSE_USERNAME', clickhouse.secret, 'username')
.withSecret('CLICKHOUSE_PASSWORD', clickhouse.secret, 'password')
.withSecret('CLICKHOUSE_PROTOCOL', clickhouse.secret, 'protocol')
// Redis
.withSecret('REDIS_HOST', redis.secret, 'host')
.withSecret('REDIS_PORT', redis.secret, 'port')
.withSecret('REDIS_PASSWORD', redis.secret, 'password')
// PG
2024-03-19 12:01:00 +00:00
.withSecret('POSTGRES_HOST', postgres.pgBouncerSecret, 'host')
.withSecret('POSTGRES_PORT', postgres.pgBouncerSecret, 'port')
.withSecret('POSTGRES_USER', postgres.pgBouncerSecret, 'user')
.withSecret('POSTGRES_PASSWORD', postgres.pgBouncerSecret, 'password')
.withSecret('POSTGRES_DB', postgres.pgBouncerSecret, 'database')
.withSecret('POSTGRES_SSL', postgres.pgBouncerSecret, 'ssl')
2024-03-04 12:56:12 +00:00
// CDN
.withSecret('CDN_AUTH_PRIVATE_KEY', cdn.secret, 'authPrivateKey')
.withSecret('CDN_CF_BASE_URL', cdn.secret, 'baseUrl')
// S3
.withSecret('S3_ACCESS_KEY_ID', s3.secret, 'accessKeyId')
.withSecret('S3_SECRET_ACCESS_KEY', s3.secret, 'secretAccessKey')
.withSecret('S3_BUCKET_NAME', s3.secret, 'bucket')
.withSecret('S3_ENDPOINT', s3.secret, 'endpoint')
// S3 Mirror
.withSecret('S3_MIRROR_ACCESS_KEY_ID', s3Mirror.secret, 'accessKeyId')
.withSecret('S3_MIRROR_SECRET_ACCESS_KEY', s3Mirror.secret, 'secretAccessKey')
.withSecret('S3_MIRROR_BUCKET_NAME', s3Mirror.secret, 'bucket')
.withSecret('S3_MIRROR_ENDPOINT', s3Mirror.secret, 'endpoint')
// S3 Audit Log
.withSecret('S3_AUDIT_LOG_ACCESS_KEY_ID', s3AuditLog.secret, 'accessKeyId')
.withSecret('S3_AUDIT_LOG_SECRET_ACCESS_KEY', s3AuditLog.secret, 'secretAccessKey')
.withSecret('S3_AUDIT_LOG_BUCKET_NAME', s3AuditLog.secret, 'bucket')
.withSecret('S3_AUDIT_LOG_ENDPOINT', s3AuditLog.secret, 'endpoint')
// Auth
2024-03-04 12:56:12 +00:00
.withSecret('SUPERTOKENS_API_KEY', supertokens.secret, 'apiKey')
.withSecret('AUTH_GITHUB_CLIENT_ID', githubOAuthSecret, 'clientId')
.withSecret('AUTH_GITHUB_CLIENT_SECRET', githubOAuthSecret, 'clientSecret')
.withSecret('AUTH_GOOGLE_CLIENT_ID', googleOAuthSecret, 'clientId')
.withSecret('AUTH_GOOGLE_CLIENT_SECRET', googleOAuthSecret, 'clientSecret')
// Hive Usage Reporting
.withSecret('HIVE_ACCESS_TOKEN', hiveUsageSecret, 'usageAccessToken')
// Persisted Documents
.withSecret(
'HIVE_PERSISTED_DOCUMENTS_CDN_ACCESS_KEY_ID',
persistedDocumentsSecret,
'cdnAccessKeyId',
)
2024-03-04 12:56:12 +00:00
// Zendesk
.withConditionalSecret(zendesk.enabled, 'ZENDESK_SUBDOMAIN', zendesk.secret, 'subdomain')
.withConditionalSecret(zendesk.enabled, 'ZENDESK_USERNAME', zendesk.secret, 'username')
.withConditionalSecret(zendesk.enabled, 'ZENDESK_PASSWORD', zendesk.secret, 'password')
// Sentry
.withConditionalSecret(sentry.enabled, 'SENTRY_DSN', sentry.secret, 'dsn')
// Other
.withSecret('ENCRYPTION_SECRET', environment.encryptionSecret, 'encryptionPrivateKey')
.deploy()
);
2022-05-18 07:26:57 +00:00
}