kawasawa.github.io

制作物や執筆記事、業務経歴をまとめた Web サイトです。

GitHubスター

1

ユーザー評価

未評価

お気に入り

0

閲覧数

12

フォーク

2

イシュー

0

README
@kawasawa

筆者の制作物、執筆記事、業務経歴をまとめた Web サイトです。

技術情報

本番運用はフロントエンドのみで、React.js を基盤とし MUI でインターフェイスを構築しています。
システムの展開と運用は GitHub で行っており、バックエンドに相当する処理は Google 内のサービスで代用しています。

[!NOTE]
開発環境用のモック (バックエンド) については README.md をご参照ください。

技術スタック
種別 使用技術
開発言語 TypeScript
JavaScript フレームワーク React.js
CSS フレームワーク MUI (Material UI)
テストフレームワーク Jest
多言語対応 i18next
HTTP クライアント Axios
バリデーター Yup
リンター ESLint , Secretlint
フォーマッター Prettier
パッケージマネージャー Yarn
ビルドツール Vite
ER 図生成ツール tbls
API 仕様書生成ツール ReDoc
API テストツール Newman
性能テストツール K6
CI/CD GitHub Actions
ホスティング GitHub Pages
ライセンススキャン FOSSA
脆弱性スキャン Snyk
カバレッジ計測 Codecov
エラー解析 Sentry
アクセス解析 Google Analytics
バッチ処理 Google Apps Script
データ永続化 Google Spread Sheets
メール配信 EmailJS , SendGrid
アーキテクチャ

Web サイトは GitHub Pages によってホスティングされています。
アクセス情報は Google Analytics で、エラー情報は Sentry で解析されます。
ページ内に表示される Qiita の記事は、Apps Script により自動取得されたものです。日次で収集されるこれらの情報は、DB の代替として永続化を担う Spread Sheets に蓄積されており、クライアントは Google Sheets API を介してレコードを抽出します。
また、問い合わせの送信はメールによって通知される方式で、この処理は EmailJS を介してフロントエンドから直接実行され SendGrid によりメール配信が行われます。

overview

ワークフロー

CI/CD は GitHub Actions によって実現されており、パイプラインは master ブランチへの merge をトリガーにスタートします。
静的解析 (ESLint)、UT (Jest)、IT (Newman)、性能テスト (K6)、ライセンススキャン (FOSSA)、脆弱性スキャン (Snyk) を順次行い、これらの検証をパスすればアプリをビルドします。
ビルドされたアプリは、ER 図 (tbls), API 仕様書 (ReDoc)、検証レポート類 (Codecov, Newman Reporter, K6 Reporter) と併せてデプロイされ、Web サイトが GitHub Pages にリリースされます。
連携された Slack からは、パイプラインのステータスを確認できます。

workflow

セキュリティ

[!WARNING]
バックエンドはモックであるため本番運用には使用しません。運用を想定したコードの作成のみになります。

サーバでは CORS ポリシーや CSRF トークンによる検証が行われており、下記に処理の流れを示す。

sequenceDiagram
    participant FE as Front-end<br/>[React.js]
    participant BE as Back-end<br/>[Express.js]

    %% 初期化処理
    par
      activate BE
      BE->>BE: initialize<br/>Express.js
      deactivate BE
    and
      activate FE
      FE->>FE: initialize<br/>Axios (withCredentials)
      deactivate FE
    end

    activate FE

    %% CSRF トークン取得
    rect rgba(0, 255, 255, 0.1)
      note left of FE: get token
      FE->>BE: GET /csrf-token<br/>[Axios]
      activate BE
      BE->>BE: create CSRF token<br/>[csurf]
      BE->>FE: 200 OK<br/>Body: { csrf_token: "abc123..." }<br/>Set-Cookie: "csrf_secret=xyz789..."<br/>(httpOnly: true, secure: true, sameSite: lax)<br/>Access-Control-Allow-Credentials: true<br/>[Express.js]
      deactivate BE
      FE->>FE: save CSRF Secret from Cookie<br/>[Browser]
      FE->>FE: save CSRF Token from Body<br/>[React.js]
    end

    %% CSRF トークン送信
    rect rgba(255, 255, 0, 0.1)
      note left of FE: send token
      FE->>FE: set CSRF Token to Header<br/>[React.js]
      FE->>FE: set CSRF Secret to Cookie<br/>[Browser]

      %% プリフライトリクエスト
      rect rgba(255, 255, 255, 0.1)
        note left of FE: preflight request
        FE->>BE: OPTIONS /send<br/>Access-Control-Request-Method: "POST"<br/>[Browser]
        activate BE
        BE->>FE: 204 NO CONTENT<br/>Access-Control-Allow-Origin: "https://example.com"<br/>Access-Control-Allow-Methods: "GET,POST,PUT,DELETE"<br/>Access-Control-Allow-Headers: "Content-Type,x-csrf-token"<br/>[cors]
        deactivate BE
        FE->>FE: check Access-Control<br/>[Browser]
        opt not allowed
            FE->>FE: Network Error<br/>[Browser]
        end
      end

      FE->>BE: POST /send<br/>Content-Type: "application/json"<br>x-csrf-token: "abc123..."<br/>Cookie: "_csrf=xyz789..."<br/>[Axios]
      activate BE
      BE->>BE: verify CSRF Token<br/>with CSRF Secret<br/>[csurf]
      opt invalid
          BE->>FE: 403 Forbidden<br/>[csurf]
      end
      BE->>BE: run API process<br/>[Express.js]
      BE->>FE: 200 OK<br/>Body: { success: true }<br/>[Express.js]
      deactivate BE
    end

    deactivate FE
クラウドインフラ

[!WARNING]
バックエンドはモックであるため本番運用には使用しません。運用を想定したコードの作成のみになります。

IaC は Terraform による AWS デプロイを想定し構築しています。
Express.js で開発された Node.js サーバを ECS で運用し、データベースに RDS を用いた場合のクラウド環境です。

infrastructure

開発情報
開発環境

開発環境でアプリケーションを動かす際は、GCP への疎通は行わず、API 処理をモックで代用します。モックは Express.js と MySQL を組み合わせた API サーバが Docker 上に展開されたもので、アプリケーションはこのサーバに対して疎通を試みます。

development

VS Code でのコーディングとテストのほか、Sourcetree でのバージョン管理、Docker での環境構築、Chrome での動作確認からなります。API サーバはローカルで実行するためのモックであり、これに対するテストやパフォーマンス測定に意義はありませんが、実際の開発現場に近い環境を用意したく必要なツール類を選定しています。
具体的なアプリは Brewfile を、ランタイムバージョンは .tool-versions をご参照ください。

種別 使用ツール
OS macOS
パッケージ管理 Homebrew
ランタイム管理 asdf
JS パッケージ管理 Yarn
Web ブラウザ Google Chrome
Docker コンテナ管理 Docker Desktop
IaC リソース管理 Terraform
コードエディタ Visual Studio Code
OpenAPI エディタ Stoplight Studio
Git クライアント Sourcetree
DB クライアント TablePlus
API クライアント Postman
性能テストツール K6
作図ツール draw.io
MCP サーバ

GitHub 等のクラウドリソースにアクセスするための既存の MCP サーバの他、ソースコード内の特定のアノテーションコメントが付与された記載をナレッジとして生成 AI の情報源にさせる自作サーバも構築しています。
収集されたコメントはベクトルデータに変換され、 Python オブジェクト形式でシリアライズしキャッシュされます。

[!NOTE]
MCP ナレッジサーバについては README.md をご参照ください。

mcp

ディレクトリ構成

プロダクトのディレクトリ構成を下記に示します。
app 配下がフロントエンド (React.js) 、mock 配下がバックエンドのモック (Express.js および MySQL) になります。

+--.github/                # GitHub 関連ファイル
|  |
|  +--instructions/        # GitHub Copilot カスタムインストラクション
|  |
|  +--prompts/             # GitHub Copilot プロンプトファイル
|  |
|  +--workflows/           # GitHub Actions ワークフロー
|
|
+--.vscode/                # VSCode 設定ファイル
|
|
+--app/                    # React.js アプリケーション
|  |
|  +--public/              # 公開ファイル
|  |
|  +--src/                 # ソースファイル
|  |  |
|  |  +--@types/           # 型定義ファイル
|  |  |
|  |  +--assets/           # 静的ファイル
|  |  |
|  |  +--components/       # ページで使用するコンポーネント
|  |  |  |
|  |  |  +--dialogs/       # ページに内包されるダイアログ
|  |  |  |
|  |  |  +--elements/      # ページに配置する部品
|  |  |  |
|  |  |  +--layouts/       # ページを構成するレイアウト
|  |  |
|  |  +--constants/        # 定数グループ
|  |  |
|  |  +--hooks/            # カスタムフック
|  |  |
|  |  +--lib/              # ライブラリラッパー
|  |  |
|  |  +--locales/          # 多言語情報
|  |  |
|  |  +--pages/            # ページ定義
|  |  |
|  |  +--schemas/          # バリデーション定義
|  |  |
|  |  +--utils/            # 汎用処理
|
|
+--docs/                   # ドキュメント類
|  |
|  +--images/              # 画像ファイル
|
|
+--mcp/                    # MCP サーバ
|  |
|  +--knowledge/           # ナレッジサーバ
|
|
+--mock/                   # モック
|  |
|  +--docker/              # Docker 関連ファイル
|  |  |
|  |  +--mysql/            # MySQL 設定ファイル
|  |  |
|  |  +--sonarqube/        # SonarQube 関連ファイル
|  |
|  +--server/              # Express.js アプリケーション
|  |  |
|  |  +--prisma/           # Prisma スキーマ定義
|  |  |
|  |  +--src/              # ソースファイル
|  |  |  |
|  |  |  +--@types/        # 型定義ファイル
|  |  |  |
|  |  |  +--api/           # API 処理
|  |  |  |
|  |  |  +--lib/           # ライブラリラッパー
|  |  |  |
|  |  |  +--middlewares/   # ミドルウェア
|  |  |  |
|  |  |  +--responses/     # レスポンス型定義
|  |  |  |
|  |  |  +--routes/        # ルーティング
|  |  |  |
|  |  |  +--schemas/       # バリデーション定義
|  |
|  +--terraform/           # Terraform 関連ファイル
|  |  |
|  |  +--environments/     # 環境別 Terraform 管理ファイル
|  |  |  |
|  |  |  +--dev/           # 開発環境
|  |  |  |
|  |  |  +--prd/           # 商用環境
|  |  |  |
|  |  |  +--stg/           # ステージング環境
|  |  |
|  |  +--modules/          # インフラモジュール
|  |  |  |
|  |  |  +--container/     # コンテナ関連 (ECS, ECR)
|  |  |  |
|  |  |  +--database/      # データベース関連 (RDS, bastion)
|  |  |  |
|  |  |  +--load_balancer/ # ロードバランサー関連 (ALB, WAF, DNS)
|  |  |  |
|  |  |  +--monitor/       # モニタリング関連 (CloudWatch, ChatOps)
|  |  |  |
|  |  |  +--network/       # ネットワーク関連 (VPC, Subnet, Endpoint)
|  |
|  +--docker-compose.yml   # モックサーバ用 Docker Compose 設定ファイル
|  |
|  +--Makefile             # モックサーバ用コマンド
|
|
+--tools/                  # ツール類
|  |
|  +--gas/                 # GAS ソースファイル
|  |
|  +--k6/                  # 負荷試験用テストコード
|  |
|  +--postman/             # API テストコード
|  |
|  +--swagger/             # OpenAPI 定義書生成仕様
|  |
|  +--tbls/                # DB 定義書生成仕様
|
コマンド

下記は開発時に使用する主要な Yarn コマンドの一覧です。

コマンド 概要
パッケージのインストール yarn install 依存パッケージをインストールする
サービスのローカル起動 yarn dev サービスをローカル環境で起動する
+-- フロントエンドのみ起動 yarn dev:app フロントエンドの Web サーバのみ起動する
(この場合、一部のコンテンツは表示されない)
+-- バックエンドのみ起動 yarn dev:mock バックエンドのモックサーバのみ起動する
静的解析の実施 yarn lint 静的解析を実施する
単体テストの実施 yarn test:ut UT を実施し、./app/coverage/ に Jest の実施結果を出力する
UT を個別に実行したい場合は yarn test:ut --testPathPattern 'path/to/test/\[id\].test.tsx'
外部結合テストの実施 yarn test:itb IT を実施し、./tools/dist/ に Newman の実施結果を出力する
(モックサーバが起動している必要がある)
性能テストの実施 yarn test:pt 性能テストを実施し、./tools/dist/ に K6 の実施結果を出力する
(モックサーバが起動している必要がある)
全資材をビルド yarn build 実行可能な形式のアプリケーションと関連するドキュメントを生成する
+-- アプリケーションのビルド yarn build:app React.js アプリケーションをトランスパイルする
+-- ライセンス情報の生成 yarn build:licenses React.js アプリケーションが利用するサードパーティーのライセンス情報を ./app/dist/ に出力する
+-- API 仕様書の生成 yarn build:openapi OpenAPI 仕様書を HTML 形式で ./tools/dist/ に出力する
+-- ER 図の生成 yarn build:er 起動中の MySQL から ER 図を生成し ./tools/dist/ に出力する
環境変数

プロダクトを本番環境にデプロイし、全機能を動作させるためには、下記の環境変数が必要になります。
※ 開発時およびテスト時に必要な環境変数は、対応する .env にすべて定義されます。

Variables (GitHub)
Name Value Summary
ACTIONS_RUNNER_DEBUG true ジョブ実行ホストの詳細ログの出力 (GitHub Actions 障害解析用)
ACTIONS_STEP_DEBUG true ジョブの詳細ログの出力 (GitHub Actions 障害解析用)
GENERATE_SOURCEMAP false マッピングファイルの生成を無効化
REACT_APP_GOOGLEAPIS_URL https://sheets.googleapis.com/v4 API 処理のリクエスト先 URL
Secrets (GitHub)
Name Value Summary
REACT_APP_GOOGLE_SHEETS_API_KEY (§1) *** Google Sheets の API キー
REACT_APP_GOOGLE_SHEETS_ID *** Google Sheets のシート ID
REACT_APP_GOOGLE_ANALYTICS_ID (§2) *** Google Analytics ID
REACT_APP_EMAILJS_PUBLIC_KEY (§3) *** EmailJS の API キー
REACT_APP_EMAILJS_SERVICE_ID (§4) *** EmailJS のサービス ID
REACT_APP_EMAILJS_TEMPLATE_ID *** EmailJS のテンプレート ID
REACT_APP_SENTRY_DSN (§5) *** Sentry のデータソース名
FOSSA_TOKEN (§6) *** FOSSA の API トークン
SNYK_TOKEN (§7) *** SNYK の API トークン
CODECOV_TOKEN (§8) *** Codecov の API トークン
SLACK_WEBHOOK_URL (§9) *** Slack の Web フック URL
ドキュメント

プロダクト開発や品質評価に関する資料を下記に列挙します。

[!NOTE]
なお、本プロダクトは自学用のプログラミングノートも兼ねており、ソース内には NOTE: で始まるコメントが多く残されています。
コメントの内容は不正確な可能性もあるため、ご容赦ください。

あえてやっていないこと
  • ブランチ戦略
    本来であれば、ブランチを main, develop, feature などに分け、レビューを経て製品版にマージするのが常套ですが、本開発ではこれを実施しません。
    大きな要因としては、比較的頻繁に変更が入る上、実験的な内容も多く、コミット履歴が荒れることを嫌ったためです。また、ポートフォリオサイトという特性上、開発者が筆者一人に限られるためレビューに有効性がありません。

  • 本番環境分離
    通常、Web サイトのリリースでは、資材をステージング環境に展開しテストを経てから本番環境に適用します。
    本開発では、アプリケーションを更新する際、即座に本番環境の資材が置き換えられます。CI/CD パイプラインで静的解析、テスト、スキャンが済んでおり、仮にリリースミスやデグレードが発生した場合も影響範囲は限られ、容易に切り戻し可能なためです。

以上