Skip to content

Commit

Permalink
feat(spa,api): add sentry for observablity (#180)
Browse files Browse the repository at this point in the history
  • Loading branch information
timonmasberg committed May 18, 2023
1 parent 8dd8bae commit 312183a
Show file tree
Hide file tree
Showing 66 changed files with 2,589 additions and 238 deletions.
22 changes: 22 additions & 0 deletions .github/actions/build-and-deploy-api/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,21 @@ name: 'build-and-deploy-api'
description: 'Builds API Project for Production and Deploys it to a given WA Slot'

inputs:
releaseVersion:
required: true
description: "Release Version (Commit or Tag)"
slot:
required: true
description: "Slot Identifier"
mongoUri:
required: true
description: "Mongo Connection URI"
sentryKey:
required: true
description: "Sentry DSN Key"
sentryAuthToken:
required: true
description: "Sentry Auth Token"
outputs:
url:
description: "API URL"
Expand All @@ -19,6 +28,9 @@ runs:
- run: envsubst < apps/api/src/.env.template > apps/api/src/.env
env:
MONGODB_URI: ${{ inputs.mongoUri }}
ENVIRONMENT_NAME: ${{ inputs.slot }}
RELEASE_VERSION: ${{ inputs.releaseVersion }}
SENTRY_KEY: ${{ inputs.sentryKey }}
shell: bash
- run: |
npx nx build api --prod
Expand All @@ -32,3 +44,13 @@ runs:
app-name: 'kordis-api'
slot-name: ${{ inputs.slot }}
package: dist/apps/api/
- name: Create Sentry release
uses: getsentry/action-release@v1
env:
SENTRY_AUTH_TOKEN: ${{ inputs.sentryAuthToken }}
SENTRY_ORG: kordis-leitstelle
SENTRY_PROJECT: kordis-api
with:
environment: ${{ inputs.slot }}
version: ${{ inputs.releaseVersion }}
sourcemaps: ./dist/apps/api
27 changes: 24 additions & 3 deletions .github/actions/build-and-deploy-spa/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,21 @@ inputs:
oauthConfig:
required: true
description: "OAuthConfig from the angular-oauth2-oidc package"
deploymentName:
releaseVersion:
required: true
description: "Unique identifier for the Deployment"
description: "Release Version (Commit or Tag)"
deploymentEnv:
required: true
description: "Azure SWA Deployment Environment"
publishToken:
required: true
description: "Azure Static Web App Deployment Token"
sentryKey:
required: true
description: "Sentry DSN Key"
sentryAuthToken:
required: true
description: "Sentry Auth Token"
outputs:
url:
description: "SPA URL"
Expand All @@ -31,9 +37,11 @@ runs:
shell: bash
env:
IS_PRODUCTION: true
DEPLOYMENT_NAME: ${{ inputs.deploymentName }}
ENVIRONMENT_NAME: ${{ inputs.deploymentEnv }}
API_URL: ${{ inputs.apiUrl }}
OAUTH_CONFIG: ${{ inputs.oauthConfig }}
RELEASE_VERSION: ${{ inputs.releaseVersion }}
SENTRY_KEY: ${{ inputs.sentryKey }}
- name: Deploy SPA
id: spa-deployment
uses: Azure/static-web-apps-deploy@v1
Expand All @@ -45,3 +53,16 @@ runs:
skip_app_build: true
skip_api_build: true
deployment_environment: ${{ inputs.deploymentEnv }}
- name: Build SPA with source maps
run: npx nx build spa --prod --source-map=true
shell: bash
- name: Create Sentry release
uses: getsentry/action-release@v1
env:
SENTRY_AUTH_TOKEN: ${{ inputs.sentryAuthToken }}
SENTRY_ORG: kordis-leitstelle
SENTRY_PROJECT: kordis-spa
with:
environment: ${{ inputs.deploymentEnv }}
version: ${{ inputs.releaseVersion }}
sourcemaps: ./dist/apps/spa
13 changes: 11 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,26 @@ jobs:
run: envsubst < apps/spa/src/environments/environment.template > apps/spa/src/environments/environment.prod.ts
env:
IS_PRODUCTION: true
DEPLOYMENT_NAME: E2E Runner
ENVIRONMENT_NAME: 'ci'
RELEASE_VERSION: ${{ github.sha }}
API_URL: http://localhost:3000/
OAUTH_CONFIG: undefined
- uses: actions/upload-artifact@v3
with:
name: env-spa-prod
path: apps/spa/src/environments/environment.prod.ts
- name: Create API Environment File
run: |
envsubst < apps/api/src/.env.template > apps/api/src/.env
echo "PORT=3000" >> .env
env:
MONGODB_URI: mongodb://127.0.0.1:27017/e2edb
ENVIRONMENT_NAME: 'ci'
RELEASE_VERSION: ${{ github.sha }}
SENTRY_KEY: ${{ secrets.SENTRY_KEY }}

- name: Build
run: npx nx affected --target=build --parallel=3
run: npx nx run-many -t build --all --parallel=3

- name: Start and prepare MongoDB for E2Es
run: ./tools/db/kordis-db.sh init e2edb
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/next-deployment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ jobs:
uses: ./.github/actions/build-and-deploy-api
with:
slot: "next"
releaseVersion: ${{ github.sha }}
mongoUri: ${{ secrets.DEV_MONGODB_URI }}
sentryKey: ${{ secrets.API_SENTRY_KEY }}
sentryAuthToken: ${{ secrets.SENTRY_AUTH_TOKEN }}
- name: Apply Database Migrations
run: ./tools/db/kordis-db.sh apply-pending-migrations
env:
Expand All @@ -43,9 +46,11 @@ jobs:
with:
apiUrl: ${{ steps.api-deployment.outputs.url }}
oauthConfig: ${{ secrets.DEV_OAUTH_CONFIG }}
deploymentName: "main.${{ github.sha }}"
releaseVersion: ${{ github.sha }}
deploymentEnv: "next"
publishToken: ${{ secrets.AZURE_STATIC_WEB_APP_TOKEN }}
sentryKey: ${{ secrets.SPA_SENTRY_KEY }}
sentryAuthToken: ${{ secrets.SENTRY_AUTH_TOKEN }}

e2e:
needs: deployment
Expand Down
20 changes: 15 additions & 5 deletions .github/workflows/preview-deployment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,20 @@ jobs:
uses: ./.github/actions/build-and-deploy-api
with:
slot: "pr${{ github.event.issue.number }}"
releaseVersion: ${{ github.sha }}
sentryKey: ${{ secrets.API_SENTRY_KEY }}
sentryAuthToken: ${{ secrets.SENTRY_AUTH_TOKEN }}
- name: Build and Deploy SPA
id: spa-deployment
uses: ./.github/actions/build-and-deploy-spa
with:
apiUrl: ${{ steps.api-deployment.outputs.url }}
oauthConfig: ${{ secrets.OAUTH_CONFIG }}
deploymentName: "PR-${{ github.event.issue.number }}.{{ github.sha }}"
deploymentEnv: "pr${{github.event.issue.number }}"
oauthConfig: ${{ secrets.DEV_OAUTH_CONFIG }}
releaseVersion: ${{ github.sha }}
deploymentEnv: "pr${{ github.event.issue.number }}"
publishToken: ${{ secrets.AZURE_STATIC_WEB_APP_TOKEN }}
sentryKey: ${{ secrets.SPA_SENTRY_KEY }}
sentryAuthToken: ${{ secrets.SENTRY_AUTH_TOKEN }}
- name: Update PR Preview Comment
uses: peter-evans/create-or-update-comment@v3.0.1
with:
Expand Down Expand Up @@ -169,15 +174,20 @@ jobs:
uses: ./.github/actions/build-and-deploy-api
with:
slot: "pr${{ github.event.pull_request.number }}"
releaseVersion: ${{ github.sha }}
sentryKey: ${{ secrets.API_SENTRY_KEY }}
sentryAuthToken: ${{ secrets.SENTRY_AUTH_TOKEN }}
- name: Build and Deploy SPA
id: spa-deployment
uses: ./.github/actions/build-and-deploy-spa
with:
apiUrl: ${{ steps.api-deployment.outputs.url }}
oauthConfig: ${{ secrets.OAUTH_CONFIG }}
deploymentName: "PR-${{ github.event.pull_request.number }}.{{ github.sha }}"
oauthConfig: ${{ secrets.DEV_OAUTH_CONFIG }}
releaseVersion: ${{ github.sha }}
deploymentEnv: "pr${{ github.event.pull_request.number }}"
publishToken: ${{ secrets.AZURE_STATIC_WEB_APP_TOKEN }}
sentryKey: ${{ secrets.SPA_SENTRY_KEY }}
sentryAuthToken: ${{ secrets.SENTRY_AUTH_TOKEN }}
- name: Update PR Preview Comment
uses: peter-evans/create-or-update-comment@v3.0.1
with:
Expand Down
4 changes: 4 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@
/coverage
package-lock.json
.github

.angular

apps/api/src/main.ts
3 changes: 3 additions & 0 deletions apps/api/src/.env.template
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
MONGODB_URI=$MONGODB_URI
ENVIRONMENT_NAME=$ENVIRONMENT_NAME
RELEASE_VERSION=$RELEASE_VERSION
SENTRY_KEY=$SENTRY_KEY
23 changes: 17 additions & 6 deletions apps/api/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { MongooseModule } from '@nestjs/mongoose';
import * as path from 'path';

import { AuthModule } from '@kordis/api/auth';
import { SentryObservabilityModule } from '@kordis/api/observability';
import { SharedKernel } from '@kordis/api/shared';

import { AppResolver } from './app.resolver';
Expand All @@ -19,13 +20,20 @@ import { GraphqlSubscriptionsController } from './controllers/graphql-subscripti
cache: true,
envFilePath: path.resolve(__dirname, '.env'),
}),
GraphQLModule.forRoot<ApolloDriverConfig>({
GraphQLModule.forRootAsync<ApolloDriverConfig>({
imports: [ConfigModule],
driver: ApolloDriver,
autoSchemaFile:
process.env.NODE_ENV !== 'production'
? path.join(process.cwd(), 'apps/api/src/schema.gql')
: true,
playground: process.env.NODE_ENV !== 'production',
useFactory: (config: ConfigService) => ({
autoSchemaFile:
config.get('NODE_ENV') !== 'production'
? path.join(process.cwd(), 'apps/api/src/schema.gql')
: true,
subscriptions: {
'graphql-ws': true,
},
playground: config.get('NODE_ENV') !== 'production',
}),
inject: [ConfigService],
}),
MongooseModule.forRootAsync({
imports: [ConfigModule],
Expand All @@ -36,6 +44,9 @@ import { GraphqlSubscriptionsController } from './controllers/graphql-subscripti
}),
SharedKernel,
AuthModule,
...(process.env.NODE_ENV === 'production' && !process.env.GITHUB_ACTIONS
? [SentryObservabilityModule]
: []),
],
providers: [AppService, AppResolver],
controllers: [GraphqlSubscriptionsController],
Expand Down
3 changes: 3 additions & 0 deletions apps/api/src/app/app.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { Injectable } from '@nestjs/common';

import { Trace } from '@kordis/api/observability';

@Injectable()
export class AppService {
@Trace()
getData(): { message: string } {
return { message: 'Welcome to api!' };
}
Expand Down
16 changes: 11 additions & 5 deletions apps/api/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { NestFactory } from '@nestjs/core';
// @formatter:off otelSdk has to imported on the very top!
// until https://github.com/open-telemetry/opentelemetry-js/issues/3450 is fixed, we have to import the oTel sdk via a relative path
// eslint-disable-next-line @nx/enforce-module-boundaries
import '../../../libs/api/observability/src/lib/oTelSdk';

import {Logger} from '@nestjs/common';
import {ConfigService} from '@nestjs/config';
import {NestFactory} from '@nestjs/core';

import {AppModule} from './app/app.module';

import { AppModule } from './app/app.module';

async function bootstrap(): Promise<void> {
const app = await NestFactory.create(AppModule, { cors: true });
const config = app.get(ConfigService);

const envPort = config.get('PORT');

const port = envPort ? +envPort : 3000;
await app.listen(port);

Expand Down
35 changes: 17 additions & 18 deletions apps/spa/src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,18 @@
import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule, Routes } from '@angular/router';
import { RouterModule } from '@angular/router';

import { AuthModule, DevAuthModule, authGuard } from '@kordis/spa/auth';
import { AuthModule, DevAuthModule } from '@kordis/spa/auth';
import {
NoopObservabilityModule,
SentryObservabilityModule,
} from '@kordis/spa/observability';

import { environment } from '../environments/environment';
import { AppComponent } from './app.component';
import { ProtectedComponent } from './protected.component';

const routes: Routes = [
{
path: '',
redirectTo: 'protected',
pathMatch: 'full',
},
{
path: 'protected',
component: ProtectedComponent,
canActivate: [authGuard],
},
{ path: '**', redirectTo: 'protected' },
];
import { AppComponent } from './component/app.component';
import { ProtectedComponent } from './component/protected.component';
import routes from './routes';

@NgModule({
declarations: [AppComponent, ProtectedComponent],
Expand All @@ -35,6 +26,14 @@ const routes: Routes = [
environment.oauth.discoveryDocumentUrl,
)
: DevAuthModule.forRoot(),
// for now, we accept that we have the sentry module and dependencies in our dev bundle as well
environment.sentryKey
? SentryObservabilityModule.forRoot(
environment.sentryKey,
environment.environmentName,
environment.releaseVersion,
)
: NoopObservabilityModule.forRoot(),
],
providers: [],
bootstrap: [AppComponent],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { TraceComponent } from '@kordis/spa/observability';

@Component({
selector: 'kordis-root',
template: ` <router-outlet></router-outlet> `,

changeDetection: ChangeDetectionStrategy.OnPush,
})
@TraceComponent()
export class AppComponent {}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { TraceComponent } from '@kordis/spa/observability';

// placeholder until we have a feature structure
@Component({
selector: 'kordis-root',
template: ` ganz geheim `,
changeDetection: ChangeDetectionStrategy.OnPush,
})
@TraceComponent()
export class ProtectedComponent {}
21 changes: 21 additions & 0 deletions apps/spa/src/app/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Routes } from '@angular/router';

import { authGuard } from '@kordis/spa/auth';

import { ProtectedComponent } from './component/protected.component';

const routes: Routes = [
{
path: '',
redirectTo: 'protected',
pathMatch: 'full',
},
{
path: 'protected',
component: ProtectedComponent,
canActivate: [authGuard],
},
{ path: '**', redirectTo: 'protected' },
];

export default routes;

0 comments on commit 312183a

Please sign in to comment.