Skip to content

Commit

Permalink
[add] 一旦デプロイするまで
Browse files Browse the repository at this point in the history
  • Loading branch information
diggymo committed Jan 8, 2024
1 parent 5779955 commit 0f6c8f1
Show file tree
Hide file tree
Showing 66 changed files with 17,220 additions and 0 deletions.
Binary file added .DS_Store
Binary file not shown.
37 changes: 37 additions & 0 deletions .github/workflows/auto-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
on:
pull_request:
paths:
- "backend/**"

jobs:
auto-test:
env:
JWT_SECRET: sample_jwt_secret
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/mydb?schema=dev
TZ: Asia/Tokyo
services:
db:
image: postgres:15.2-alpine
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: mydb
ports:
- '5432:5432'
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./backend
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- run: yarn global add @nestjs/cli
- run: yarn install --frozen-lockfile
- run: yarn prisma generate
- run: yarn test --forceExit --collect-coverage
- uses: romeovs/lcov-reporter-action@v0.3.1
with:
lcov-file: ./backend/coverage/lcov.info
github-token: ${{ secrets.GITHUB_TOKEN }}
29 changes: 29 additions & 0 deletions .github/workflows/cdk-diff.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: CDKのdiffを出力します

on:
pull_request:
types:
- opened
- synchronize

jobs:
diff:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./iac
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- run: |
npm install
npm install -g aws-cdk
- name: CDKの差分を出力します
run: cdk diff
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: ap-northeast-1
28 changes: 28 additions & 0 deletions .github/workflows/iac-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: CDKをデプロイします

on:
push:
branches:
- main

jobs:
deploy:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./iac
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- run: |
npm install
npm install -g aws-cdk
- name: Deploy to AWS
run: cdk deploy --require-approval never
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: ap-northeast-1
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,13 @@
# todo-diggymo

## IaC

[IaC](./iac)ディレクトリをご確認ください。
クラウドでの環境構築方法とそのコードが含まれています。


## バックエンドサーバー

[backend](./backend)ディレクトリをご確認ください。
ローカルでの環境構築方法やソースコード/テストコード、および、[全体構成の説明](./backend/ARCHITECTURE.md)が含まれています。

18 changes: 18 additions & 0 deletions backend/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/dist
/node_modules

# Postgresのデータ
database/postgres

# DynamoDBのデータ
database/dynamodb

# 秘匿情報
.env

# カバレッジ
coverage


backend/dist
lambda-deploy-package
4 changes: 4 additions & 0 deletions backend/.env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/mydb?schema=dev"
JWT_SECRET="jwt_secret"

TZ=Asia/Tokyo
35 changes: 35 additions & 0 deletions backend/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
tsconfigRootDir: __dirname,
sourceType: 'module',
},
plugins: ['@typescript-eslint/eslint-plugin'],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
root: true,
env: {
node: true,
jest: true,
},
ignorePatterns: ['.eslintrc.js'],
rules: {
"prettier/prettier": [
"error",
// .prettierrc は用意せずここに集約
{
"singleQuote": true,
"trailingComma": "all",
"printWidth": 120
}
],
"@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }],
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
},
};
50 changes: 50 additions & 0 deletions backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# compiled output
/dist
/node_modules

# Logs
logs
*.log
npm-debug.log*
pnpm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# OS
.DS_Store

# Tests
/coverage
/.nyc_output

# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

# Postgresのデータ
database/postgres

# DynamoDBLocal
database/dynamodb

# 秘匿情報
.env

# カバレッジ
coverage

backend/dist
lambda-deploy-package
8 changes: 8 additions & 0 deletions backend/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"eslint.validate": [
"javascript"
]
}
38 changes: 38 additions & 0 deletions backend/ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# TODOアプリケーションについて

## 言語/FWの選定

言語にはTypeScriptを採用しました。
また、フレームワークにはNest.jsを採用しました。TypeScriptで記述ができるフレームワークはExpress, Nest.js, Next.jsなどが考えられますが、バックエンドのロジックに集中することができる点、主要な機能が公式に提供されている点、機能ごとにモジュール分割しやすい点を加味してNest.jsを選択しました。

## データ永続化方法の検討

データを永続化するためにRDBを選択しました。また、RDBとしてPostgresQLを選択しました。

また、アプリケーションからPostgresQLへアクセスするORMとしてPrismaを採用しました。TypeORMやSequelizeなど他にもORMがありますが、エンティティがシンプルなオブジェクトであり学習コストが低く、また型が強力に設定されていてエラーを事前に防げる点を加味してPrismaを選択しました。

## TODOアプリケーションの構成

TODOアプリケーションは、複数のモジュールから構成されています。主なモジュールは以下の通りです。

- auth(認証・認可関連)
- prisma(データベースアクセス関連)
- todo(TODO関連)
- user(ユーザー関連)

技術的な関心で分割するのではなくモジュールごとに分割することで、特定の機能を追加開発する際に関連するファイル同士の距離を近くすることができます。
また、依存する外部のモジュールのことを気にせず開発やテストの実装をすることができます。
また、将来的にアプリケーションの規模が大きくなった際にモジュールを分割してマイクロサービスに移行しやすいとも考えています。

各モジュールの中身は、主に`controller``service`の2つのレイヤーから構成されています。
`dto`/`exception-filter`/`guards`/`decorator`/`controller``controller`のレイヤに属しており、`entity`/`service``service`のレイヤに属していると考えています。
`controller`レイヤは、HTTPに関する外部とのやりとりの責任を担うレイヤです。したがってリクエストボディのバリデーションやURL構成やエラーのレスポンス変換もこのクラスで行います。
また、`service`レイヤはアプリケーションのユースケースやドメインの振る舞いを表現するクラスです。ビジネスロジックによるバリデーションやデータベースとの連携はここで行います
今回の仕様上、`repository`というレイヤは不要と考えており作成していません。`repository`レイヤは本来データベースとの連携の責務を持ちますが、今回は`service`レイヤに持たせています。
というのも、今回の仕様複雑ではなくアプリケーションのユースケースやドメインの振る舞いが少なかったためです。もし各ドメインの複雑さが将来的に上がる場合はrepositoryを設けなければならないと考えています。

## エラーハンドリングについて

ビジネスロジックのバリデーションによってエラーが発生することがあります。その場合は`service`レイヤでエラーを発生させ、そのエラーを`controller`レイヤの`controller`もしくは`exception-filter`(Nest.jsが提供するExceptionFilter)でキャッチする仕組みを理想だと考えています。
ですが、今回の場合だとエラーのパターンが少ないため、グローバルなExceptionFilterで一括してエラーハンドリングをしています。ビジネスロジックのバリデーションが増えてきたら、各モジュールの`exception-filter`もしくは`controller`でハンドリングすることを考えます。

41 changes: 41 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
##############
# for BUILD
##############
FROM node:18-alpine

WORKDIR /usr/src/app

COPY package*.json yarn.lock ./

RUN yarn global add @nestjs/cli
RUN yarn install --frozen-lockfile

COPY . .

ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}

RUN yarn prisma generate

RUN yarn run build

##############
# for RUN
##############
FROM node:18-alpine

ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}

WORKDIR /usr/src/app

COPY --from=0 /usr/src/app/dist ./dist
COPY --from=0 /usr/src/app/node_modules ./node_modules

# 環境変数の合成
# CDKでDATABASE_URLを動的に生成することができないため、実行時に生成されるよう.envを調整する
RUN echo 'DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}?schema=public' > .env

USER node

CMD ["node", "dist/src/main.js"]
50 changes: 50 additions & 0 deletions backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
TODOアプリケーションです。

システム・アプリケーションの構成に関しては[ARCHITECTURE.md](./ARCHITECTURE.md)に記載しています。

## 使い方



## 事前準備

```
# DBの準備
docker-compose up -d
# 環境変数用意
cp .env.sample .env
# パッケージインストール
yarn install
# migration
yarn prisma migrate dev
# テストデータとしてユーザーを作成します
yarn prisma db seed
```


## サーバー起動

```
# ホットリローディングあり
yarn start:dev
# ホットリローディングなし
yarn start
```

## APIのスキーマについて

APIのスキーマはOpenAPIのフォーマットで自動出力されるようになっています。

サーバー起動後に `http://localhost:3000/api`にアクセスして閲覧してください。

## 自動テストについて

以下のコマンドで実行されます。Postgresのコンテナが動作している必要があります。また、テスト用のDBが複数作成されるので注意して下さい。

```
yarn test
```
19 changes: 19 additions & 0 deletions backend/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash -eu

rm -rf node_modules
# npm i
# npm run build
# npm prune --production
yarn
yarn run build -- --config nest-cli.serverless.json
yarn --production
# pnpm i
# pnpm run build
# pnpm prune --prod
rm -rf lambda-deploy-package
mkdir lambda-deploy-package
cp -R dist lambda-deploy-package
cp -R node_modules lambda-deploy-package
# npm run start:prod
node dist/src/entrypoint/serverless.js
# pnpm run start:prod
Loading

0 comments on commit 0f6c8f1

Please sign in to comment.