slidict.io のデプロイメントパイプラインの全体像
-
GitHub Actions を活用した自動化フロー
-
Conventional Commits による自動リリースノート作成
-
Azure Kubernetes Service (AKS) への継続的デプロイメント
-
3つの環境(Preview, Staging, Production)での段階的デプロイ
-
Preview: main ブランチ push 時に自動デプロイ
-
Staging: PR に staging ラベル付与で手動デプロイ
-
Production: GitHub Release 作成時に自動デプロイ
📋 目次
-
デプロイフロー概要
-
GitHub Actions ワークフロー
-
Conventional Commits setup
-
リリースノート生成
-
Docker イメージビルド
-
AKS デプロイメント詳細
-
Release Tasks 機構
-
環境別設定
-
監視・通知
-
ベストプラクティス
🔄 デプロイフロー全体像
| 環境 | トリガー | 用途 |
|---|---|---|
Preview |
main ブランチへの push |
開発中の最新機能 |
Staging |
PR に staging ラベル付与 |
リリース前の最終検証 |
Production |
GitHub Release 作成 |
ユーザー向け本番環境 |
各環境は独立した AKS クラスタ設定を持ち、段階的なテストと検証が可能
プロジェクトの基本ルール:
-
prefix:
feat:,fix:,docs:,style:,refactor:,test:,chore:など -
言語: 日本語で記述(50文字程度が目安)
-
句点: 語尾に句点を付けない
feat: ユーザープロフィールに自己紹介欄を追加
fix: スライド保存時のエラーハンドリングを修正
docs: デプロイメント手順を更新
💡 効果: コミット履歴がしっかり解析でき、自動でリリースノート を生成!
# main ブランチへの push で以下が自動実行される
- name: Create CHANGELOG
uses: requarks/changelog-action
with:
fromTag: 最後のリリースタグ
toTag: 現在のバージョンタグ
excludeTypes: "" # すべてのコミットタイプを含める
includeInvalidCommits: false # マージコミットは自動除外
自動除外されるコミット:
* Merge pull request …
* Merge branch …
* その他マージ関連コミット
これにより、ユーザー向けリリースノートが自動生成される
name: main-ci
on:
push:
branches: [main]
workflow_dispatch: # 手動実行も可能
jobs:
main:
# 1. Changelog 自動生成
# 2. Draft Release 作成
# 3. Kroki ダイアグラムサービスをデプロイ
# 4. Preview 環境へのフルデプロイ
実行時間: 約 10~15分
- name: Build and push image to DockerHub
uses: docker/build-push-action
with:
tags: |
slidict/slidict.io:preview-{{COMMIT_SHA}}
build-args: |
RAILS_ENV=preview
SECRET_KEY_BASE_DUMMY=dummy-secret-key
GITHUB_SHA={{COMMIT_SHA}}
-
イメージタグ:
環境-コミットSHAで一意性を確保 -
ビルドキャッシュ: 層ごとにキャッシュされ、効率化
-
DockerHub: プライベートレジストリへ自動プッシュ
# 1. 証明書管理(cert-manager)
- name: Apply cert-manager manifests
run: |
kubectl apply -f cert/secret.yml
kubectl apply -f cert/clusterissuer.yml
kubectl apply -f cert/certificate.yml
# 2. Redis デプロイ
- name: Deploy redis
# 3. Chrome ブラウザサービス(スクリーンショット用)
- name: Deploy chrome
# 4. Sidekiq Worker(バックグラウンドジョブ)
- name: Deploy worker
# 5. データベースマイグレーション
- name: Wait for migration to complete
run: |
kubectl wait --for=condition=complete \
--timeout=120s job/$POD_PREFIX-migrate
# 6. Release Tasks 実行
# 初回デプロイ時のみ実行される一度限りのタスク
# 7. メインアプリケーションデプロイ
- name: Deploy pod and update ingress
with:
manifests: |
ingress.yml
app.yml
# 8. Auto Scaling 設定
- name: Deploy horizontal-pod-autoscaler
一度だけ実行したいタスクを管理
# lib/release_tasks/backfill_feature_flag.rb
module ReleaseTasks
class BackfillFeatureFlag < ReleaseTasks::Base
def run
FeatureFlag.find_each do |flag|
flag.update!(enabled: true)
end
end
end
end
-
実行履歴:
release_tasksテーブルで管理 -
二重実行防止:
executed_atで判定 -
手動実行:
make release-tasksコマンドで可能
GitHub Release トリガー
name: production-ci
on:
release:
types: [released] # Draft Release が published されたら実行
permissions: write-all
jobs:
deploy_production:
uses: ./.github/workflows/call-deploy-ci.yml
with:
ENVIRONMENT: "production"
ENVIRONMENT_URL: "https://slidict.io"
POD_PREFIX: "slidict-io"
重要: Draft Release → Published Release に変更されたとき
PR の staging ラベルでトリガー
name: staging-ci
on:
pull_request_target:
branches: [main]
types: [labeled, synchronize, reopened]
jobs:
deploy_staging:
if: contains(github.event.pull_request.labels.*.name, 'staging')
# → staging ラベルがついている場合のみ実行
用途: 本番リリース前の最後の検証環境
🎯 リリースプロセス全体
1️⃣ コード開発
└─ Conventional Commits でコミット
2️⃣ main ブランチへ merge
└─ main-ci が自動実行
└─ Changelog automatically generated
└─ Draft Release created
└─ Preview 環境へデプロイ ✨
3️⃣ Staging 検証(オプション)
└─ PR に staging ラベル追加
└─ staging-ci が実行
└─ staging.slidict.io で最終検証
4️⃣ GitHub Release の Published
└─ production-ci が自動実行
└─ production 環境へデプロイ 🚀
5️⃣ ユーザーが新機能を利用可能 🎉
ERB テンプレートで環境別設定を制御
# manifests/expansion.rb(自動実行)
ruby manifests/expansion.rb \
manifests/azure-kubernetes/production/cert/secret.yml
# 展開対象
- Azure Service Principal 認証情報
- DNS 設定
- 各環境別リソース
# manifests/azure-kubernetes/production/app.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: slidict-io-production
spec:
replicas: <%= ENV['PRODUCTION_REPLICAS'] %> # 環境変数で制御
📊 環境構成の違い
| 要素 | Preview | Staging | Production |
|---|---|---|---|
kubeconfig |
AKS Slidict |
AKS Slidict |
AKS Slidict |
Pod Replicas |
2 |
3 |
5 |
Min/Max HPA |
2/10 |
3/15 |
5/30 |
Resource Limits |
small |
medium |
large |
DNS |
*.svc.cluster.local |
*.svc.cluster.local |
本番FQDN |
Monitoring |
基本 |
基本 |
Prometheus + Grafana |
# manifests/azure-kubernetes/nagios/nagios.yaml
monitoring:
- healthz: /healthz # アプリ起動確認
- sns_login: /healthz/sns_login # SNS 認証確認
- https: https://slidict.io(12時間間隔)
configuration:
debug_level: 2048
debug_verbosity: 2
configmap: docker/nagios/nagios.cfg
注意: ホスト名は azure-kubernetes 内のサービス DNS を使用
* ✅ *.svc.cluster.local
* ❌ slidict.io や origin.slidict.io(外部URL)
manifests/azure-kubernetes/
├── grafana/
│ ├── datasources.yml (Prometheus接続)
│ ├── dashboards/
│ │ ├── app-metrics.json (アプリメトリクス)
│ │ ├── k8s-cluster.json (クラスタ状態)
│ │ └── sidekiq-jobs.json (バックグラウンドジョブ)
│ └── grafana-deployment.yaml
-
Prometheus Operator で自動スクレイピング
-
Alert Rules で異常検知
-
通知: Slack, Email など
AKS Cluster 内で動作
manifests/azure-kubernetes/kroki/
├── mermaid-deployment.yaml # フローチャート
├── bpmn-deployment.yaml # ビジネスプロセス
├── excalidraw-deployment.yaml # 手書き図
├── kroki-deployment.yaml # メインサービス
└── kroki-ingress.yaml
-
slidict.io エディタから図を生成・埋め込み可能
-
完全クローズド環境で実行(外部API呼び出しなし)
# 開発環境立ち上げ
docker compose up -d
# Rails サーバー起動
docker compose exec app bin/dev
# テスト実行(codex環境)
RAILS_ENV=codex bundle exec rspec
# キャッシュリセット(Propshaft の問題回避)
rm -rf public/assets/
docker compose restart app
重要: public/assets/ が存在するとプリコンパイル済みアセットを読み込み、
動的生成がスキップされるため、新規のアセットが見つからなくなる
定期実行ジョブの設定
# config/sidekiq.yml
:schedule:
check_sns_login_health:
cron: '0 * * * *' # 毎時間
class: SnSLoginHealthCheckJob
regenerate_slide_thumbnails:
cron: '0 3 * * *' # 毎日 3時
class: RegenerateSlideThumbailsJob
-
schedules を使用: https://github.com/sidekiq-scheduler/sidekiq-scheduler
-
キャッシュからの実行: Redis database 15
-
テスト: spec は
config/sidekiq_schedule_spec.rbではなく、実装に組み込む
異なる用途で DB 分離
| Database | 用途 |
|---|---|
11 |
Redcord(キー値ストア) |
12 |
ActionCable(リアルタイム通信) |
14 |
キャッシュストア |
15 |
Sidekiq(バックグラウンドジョブ) |
# Redis CLI でデータベース確認
redis-cli -n 15 KEYS "*" # Sidekiq のキー一覧
📝 ドキュメント整備
コード変更時は必ず関連ドキュメントも更新
docs/
├── feature-specs.md # 機能仕様一覧
├── groups.md # グループ共有機能
├── help-center-and-support.md
├── slide_deck_structure.md
├── release-tasks.md # リリースタスク機構
├── infrastructure-manifests.md
├── slide-moderation.md
├── editor/ # エディタ仕様
└── mcp/ # MCP サーバー仕様
-
Help Articles:
docs/seeds/help_articles/で更新 -
シード管理: ユーザー向けの情報は整備が必須
-
☐ コミットメッセージが Conventional Commits に準拠
-
☐ RSpec テストが全て PASS:
make rspec -
☐ RuboCop が PASS:
make rubocop -
☐ Brakeman セキュリティ確認:
docker compose exec base bundle exec brakeman -
☐ ERB フォーマット確認:
make htmlbeautifier args='*/.erb' -
☐ TypeScript/JavaScript ビルド:
yarn build -
☐ 関連ドキュメント更新
-
☐ Release Tasks が必要な場合は実装済み
🚀 デプロイ実行
# 1. コード確認・テスト
make rspec
make rubocop
# 2. コミット & push to main
git add .
git commit -m "feat: 新機能を実装"
git push origin main
# 3. GitHub Actions 自動実行
# → Draft Release が作成される
# 4. Release 確認(稼働状況・クリティカルバグなし)
# 5. GitHub Release を Published に変更
# → production-ci が自動実行
# 6. 本番環境にデプロイ完了 🎉
🐛 デプロイ失敗時の対応
# 1. GitHub Actions ログを確認
# → Workflow ページで詳細ログを確認
# 2. AKS ポッド状態を確認
kubectl get pods -n default
# 3. ポッドログを確認
kubectl logs <pod-name> -n default
# 4. デバッグモードで再実行
# → Workflow の "Run" ボタンで再実行
# OR
# → デバッグログを有効にして実行
💡 ベストプラクティス
-
小分けコミット: 1つの PR = 複数の小さなコミット
-
Conventional Commits: 自動リリースノート生成に必須
-
テスト駆動開発: テストなしで main にマージしない
-
Preview 環境活用: main-ci で自動デプロイされる
-
Staging 検証: 本番向け大型変更は staging でテスト
-
Release Notes 確認: Draft Release をレビューしてから Published
-
Monitoring 監視: 本番デプロイ後の動作確認は必須
-
ドキュメント同期: コード変更とドキュメント更新は同時に
| ワークフロー | 処理内容 | 実行時間 |
|---|---|---|
main-ci |
Changelog + Docker Build + AKS Deploy |
10~15分 |
staging-ci |
Docker Build + AKS Deploy |
8~12分 |
production-ci |
Docker Build + AKS Deploy |
8~12分 |
最適化のポイント: * Docker BuildKit によるレイヤーキャッシュ * 並列ジョブ実行(cert, setup_configmap 等) * DockerHub へのプッシュ(レジストリ内キャッシュ活用)
🔄 ロールバック戦略
本番環境での問題発生時
# 1. 前のイメージタグを確認
kubectl get deployment slidict-io-production \
-o jsonpath='{.spec.template.spec.containers[0].image}'
# 2. 前のバージョンにロールアウト
kubectl rollout history deployment/slidict-io-production
kubectl rollout undo deployment/slidict-io-production
# 3. 状態確認
kubectl get pods
kubectl logs <新しいpod>
GitHub Releases でも可能: 前のバージョンタグから新しい Release を作成
GitHub Actions Secrets の活用
GitHub Repository Secrets:
- APP_ID: GitHub App ID
- APP_PRIVATE_KEY: GitHub App の秘密鍵
- AKS_SLIDICT_KUBECONFIG: AKS kubeconfig
- AZURE_SUBSCRIPTION_ID: Azure サブスクリプション ID
- DNS_SP: DNS 用サービスプリンシパル(JSON)
- DOCKERHUB_USERNAME: Docker Hub ユーザー名
- DOCKERHUB_TOKEN: Docker Hub トークン
✅ セキュリティ:
* すべてのシークレットはマスクされる
* ログには出力されない
* PR では利用できない(pull_request_target を使用)
📈 スケーリング戦略
HPA (Horizontal Pod Autoscaler) による自動スケール
# manifests/azure-kubernetes/production/horizontal-pod-autoscaler.yml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: slidict-io-production-hpa
spec:
scaleTargetRef:
name: slidict-io-production
minReplicas: 5
maxReplicas: 30
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
🎯 ノウハウ共有
よくある質問と回答
Q: Release Task を再実行したい
A: release_tasks テーブルの該当レコードの executed_at を NULL にする
Q: Preview デプロイが失敗した
A: public/assets/ ディレクトリを削除して再起動
Q: Staging で本番同様にテストしたい A: staging ラベルで PR をデプロイし、staging.slidict.io で検証
Q: Release Notes を手動で修正したい A: Draft Release を編集して公開(GitHub の UI から)
Q: Rollback したい
A: kubectl rollout undo で前バージョンに戻す
🏆 まとめ
slidict.io のデプロイメントパイプラインの特徴
✨ 自動化: Conventional Commits → 自動 Changelog 生成
🚀 段階的デプロイ: Preview → Staging → Production
🔒 安全性: PR staging ラベルで検証 → Release で本番化
📊 可視化: GitHub Actions + Grafana + Nagios
⚡ スケーラビリティ: HPA による自動スケール
🔄 復旧性: ロールバック機構で迅速な復旧
💡 DevOps 文化: コード品質とドキュメント整備が鍵
🚀 さいごに
GitHub Actions + Conventional Commits + AKS = 強力な CI/CD
デプロイパイプラインを理解することで、 チーム全体の開発効率と品質が向上する
Happy Deploying! 🎉
本スライドの最新版は slidict.io で公開中