ファイルマージ
ファイルマージは、複数の設定ファイルからワークフローを構成する Probe の強力な機能です。設定の再利用、環境固有のカスタマイズ、モジュラーなワークフロー設計を可能にします。このガイドでは、マージ戦略、パターン、ベストプラクティスについて詳しく説明します。
ファイルマージの基礎
Probe はカンマ区切りのファイルパスを使用して複数の YAML ファイルのマージをサポートします:
probe base.yml,environment.yml,overrides.yml
ファイルは左から右の順序でマージされ、後のファイルが前のファイルを上書きします。
基本的なマージ例
base.yml:
name: API Health Check
description: Basic API monitoring
vars:
API_TIMEOUT: 30s
RETRY_COUNT: 3
jobs:
- name: Health Check
id: health-check
defaults:
http:
timeout: "{{vars.API_TIMEOUT}}"
headers:
User-Agent: "Probe Monitor"
steps:
- name: API Health
uses: http
with:
url: "{{vars.API_URL}}/health"
test: res.code == 200
production.yml:
vars:
API_URL: https://api.production.company.com
API_TIMEOUT: 10s
PROD_API_TOKEN: prod_token_123
jobs:
- name: Health Check # 同じジョブ名でマージされる
defaults:
http:
timeout: 10s # API_TIMEOUTで上書きされる
headers:
Authorization: "Bearer {{vars.PROD_API_TOKEN}}" # 追加される
probe base.yml,production.yml
の結果:
name: API Health Check
description: Basic API monitoring
vars:
API_URL: https://api.production.company.com
API_TIMEOUT: 10s # 上書きされた
RETRY_COUNT: 3 # 保持された
PROD_API_TOKEN: prod_token_123 # 追加された
jobs:
- name: Health Check # base から保持
id: health-check
defaults:
http:
timeout: 10s # 上書きされた
headers:
User-Agent: "Probe Monitor" # 保持された
Authorization: "Bearer {{vars.PROD_API_TOKEN}}" # 追加された
steps:
- name: API Health
uses: http
with:
url: "{{vars.API_URL}}/health" # マージされた API_URL を使用
test: res.code == 200
マージ戦略
1. 環境ベース設定
基本設定を環境固有設定から分離します:
base-monitoring.yml:
name: Service Monitoring
description: Monitor critical services
defaults:
http:
headers:
User-Agent: "Probe Monitor v1.0"
jobs:
api-health:
name: API Health Check
steps:
- name: Health Endpoint
uses: http
with:
url: "{{vars.API_BASE_URL}}/health"
test: res.code == 200
- name: Metrics Endpoint
uses: http
with:
url: "{{vars.API_BASE_URL}}/metrics"
test: res.code == 200
database-health:
name: Database Health
steps:
- name: Database Ping
uses: http
with:
url: "{{vars.DB_API_URL}}/ping"
test: res.code == 200
development.yml:
vars:
API_BASE_URL: http://localhost:3000
DB_API_URL: http://localhost:5432
defaults:
http:
timeout: 60s # 開発環境では緩い設定
staging.yml:
vars:
API_BASE_URL: https://api.staging.company.com
DB_API_URL: https://db.staging.company.com
defaults:
http:
timeout: 30s
headers:
X-Environment: staging
production.yml:
vars:
API_BASE_URL: https://api.company.com
DB_API_URL: https://db.company.com
defaults:
http:
timeout: 10s # プロダクション用の厳格なタイムアウト
headers:
X-Environment: production
Authorization: "Bearer {{vars.PROD_API_TOKEN}}"
jobs:
# プロダクション固有の監視を追加
security-scan:
name: Security Scan
steps:
- name: Security Health Check
uses: http
with:
url: "{{vars.API_BASE_URL}}/security/health"
test: res.code == 200
使用方法:
# 開発環境
probe base-monitoring.yml,development.yml
# ステージング環境
probe base-monitoring.yml,staging.yml
# プロダクション環境(追加のセキュリティチェックを含む)
probe base-monitoring.yml,production.yml
2. レイヤード設定アーキテクチャ
最大限の柔軟性のために設定をレイヤーで構築します:
レイヤー1 - 基盤 (foundation.yml):
name: Multi-Service Health Check
description: Foundation configuration for service monitoring
defaults:
http:
headers:
User-Agent: "Probe Health Monitor"
Accept: "application/json"
jobs:
connectivity:
name: Basic Connectivity
steps:
- name: Network Check
echo: "Checking network connectivity"
レイヤー2 - コアサービス (core-services.yml):
jobs:
user-service:
name: User Service Health
needs: [connectivity]
steps:
- name: User API Health
uses: http
with:
url: "{{vars.USER_SERVICE_URL}}/health"
test: res.code == 200
order-service:
name: Order Service Health
needs: [connectivity]
steps:
- name: Order API Health
uses: http
with:
url: "{{vars.ORDER_SERVICE_URL}}/health"
test: res.code == 200
レイヤー3 - 拡張サービス (extended-services.yml):
jobs:
notification-service:
name: Notification Service Health
needs: [connectivity]
steps:
- name: Notification API Health
uses: http
with:
url: "{{vars.NOTIFICATION_SERVICE_URL}}/health"
test: res.code == 200
analytics-service:
name: Analytics Service Health
needs: [connectivity]
steps:
- name: Analytics API Health
uses: http
with:
url: "{{vars.ANALYTICS_SERVICE_URL}}/health"
test: res.code == 200
レイヤー4 - 統合テスト (integration.yml):
jobs:
integration-tests:
name: Integration Tests
needs: [user-service, order-service]
steps:
- name: User-Order Integration
uses: http
with:
url: "{{vars.API_GATEWAY_URL}}/integration/user-order"
test: res.code == 200
end-to-end:
name: End-to-End Tests
needs: [integration-tests, notification-service]
steps:
- name: Complete Workflow Test
uses: http
with:
url: "{{vars.API_GATEWAY_URL}}/e2e/complete"
test: res.code == 200
レイヤー5 - 環境 (environment.yml):
vars:
USER_SERVICE_URL: https://users.api.company.com
ORDER_SERVICE_URL: https://orders.api.company.com
NOTIFICATION_SERVICE_URL: https://notifications.api.company.com
ANALYTICS_SERVICE_URL: https://analytics.api.company.com
API_GATEWAY_URL: https://gateway.api.company.com
defaults:
http:
timeout: 15s
組み合わせの使用例:
# コアサービスのみ
probe foundation.yml,core-services.yml,environment.yml
# 統合なしの拡張サービス
probe foundation.yml,core-services.yml,extended-services.yml,environment.yml
# 統合テスト付きの完全スイート
probe foundation.yml,core-services.yml,extended-services.yml,integration.yml,environment.yml
3. 機能ベースの構成
混合して組み合わせることができる機能でワークフローを構成します:
base-workflow.yml:
name: Modular Service Test
description: Base workflow with modular features
jobs:
setup:
name: Test Setup
steps:
- name: Initialize Test Environment
echo: "Test environment initialized"
outputs:
test_session_id: "{{random_str(16)}}"
start_time: "{{unixtime()}}"
feature-authentication.yml:
jobs:
authentication-tests:
name: Authentication Tests
needs: [setup]
steps:
- name: Login Test
id: login
uses: http
with:
url: "{{vars.API_URL}}/auth/login"
method: POST
body: |
{
"username": "{{vars.TEST_USERNAME}}",
"password": "{{vars.TEST_PASSWORD}}"
}
test: res.code == 200
outputs:
access_token: res.body.json.access_token
- name: Token Validation
uses: http
with:
url: "{{vars.API_URL}}/auth/validate"
headers:
Authorization: "Bearer {{outputs.login.access_token}}"
test: res.code == 200
feature-user-management.yml:
jobs:
user-management-tests:
name: User Management Tests
needs: [authentication-tests]
steps:
- name: Create User
id: create-user
uses: http
with:
url: "{{vars.API_URL}}/users"
method: POST
headers:
Authorization: "Bearer {{outputs.authentication-tests.access_token}}"
body: |
{
"name": "Test User {{random_str(6)}}",
"email": "test{{random_str(8)}}@example.com"
}
test: res.code == 201
outputs:
user_id: res.body.json.user.id
- name: Get User
uses: http
with:
url: "{{vars.API_URL}}/users/{{outputs.create-user.user_id}}"
headers:
Authorization: "Bearer {{outputs.authentication-tests.access_token}}"
test: res.code == 200
- name: Delete User
uses: http
with:
url: "{{vars.API_URL}}/users/{{outputs.create-user.user_id}}"
method: DELETE
headers:
Authorization: "Bearer {{outputs.authentication-tests.access_token}}"
test: res.code == 204
feature-performance.yml:
jobs:
performance-tests:
name: Performance Tests
needs: [setup]
steps:
- name: Response Time Test
uses: http
with:
url: "{{vars.API_URL}}/performance/test"
test: res.code == 200 && res.time < 1000
outputs:
response_time: res.time
- name: Load Test
uses: http
with:
url: "{{vars.API_URL}}/performance/load"
method: POST
body: |
{
"concurrent_users": 10,
"duration": 30
}
test: res.code == 200
outputs:
load_test_passed: res.body.json.success
feature-reporting.yml:
jobs:
test-reporting:
name: Test Reporting
needs: [setup] # 他のすべてのテスト完了後に実行
steps:
- name: Generate Report
echo: |
Test Execution Report
====================
Session ID: {{outputs.setup.test_session_id}}
Execution Time: {{unixtime() - outputs.setup.start_time}} seconds
Test Results:
{{jobs.authentication-tests ? "Authentication: " + (jobs.authentication-tests.success ? "✅ Passed" : "❌ Failed") : "Authentication: ⏸️ Not Run"}}
{{jobs.user-management-tests ? "User Management: " + (jobs.user-management-tests.success ? "✅ Passed" : "❌ Failed") : "User Management: ⏸️ Not Run"}}
{{jobs.performance-tests ? "Performance: " + (jobs.performance-tests.success ? "✅ Passed" : "❌ Failed") : "Performance: ⏸️ Not Run"}}
{{jobs.performance-tests ? "Performance Metrics:" : ""}}
{{jobs.performance-tests ? "- Response Time: " + outputs.performance-tests.response_time + "ms" : ""}}
{{jobs.performance-tests ? "- Load Test: " + (outputs.performance-tests.load_test_passed ? "✅ Passed" : "❌ Failed") : ""}}
機能の組み合わせ:
# 認証のみ
probe base-workflow.yml,feature-authentication.yml,feature-reporting.yml,env.yml
# ユーザー管理(認証を含む)
probe base-workflow.yml,feature-authentication.yml,feature-user-management.yml,feature-reporting.yml,env.yml
# パフォーマンステストのみ
probe base-workflow.yml,feature-performance.yml,feature-reporting.yml,env.yml
# 完全な機能スイート
probe base-workflow.yml,feature-authentication.yml,feature-user-management.yml,feature-performance.yml,feature-reporting.yml,env.yml
高度なマージパターン
1. オーバーライドパターン
特別なケースには特定のオーバーライドファイルを使用します:
base-config.yml:
name: Service Monitor
vars:
API_TIMEOUT: 30s
RETRY_COUNT: 3
LOG_LEVEL: info
defaults:
http:
timeout: 30s
jobs:
health-check:
name: Health Check
steps:
- name: API Health
uses: http
with:
url: "{{vars.API_URL}}/health"
test: res.code == 200
debug-overrides.yml:
vars:
LOG_LEVEL: debug
API_TIMEOUT: 120s # デバッグ用の長いタイムアウト
defaults:
http:
timeout: 120s
jobs:
health-check:
steps:
- name: API Health
uses: http
with:
url: "{{vars.API_URL}}/health"
test: res.code == 200
outputs:
# デバッグ出力を追加
debug_response_headers: res.headers
debug_response_time: res.time
debug_response_size: res.body_size
# デバッグステップを追加
- name: Debug Information
echo: |
Debug Information:
Response Time: {{outputs.debug_response_time}}ms
Response Size: {{outputs.debug_response_size}} bytes
Content Type: {{outputs.debug_response_headers["content-type"]}}
load-test-overrides.yml:
vars:
CONCURRENT_REQUESTS: 100
TEST_DURATION: 300s
jobs:
# health-check をロードテストでオーバーライド
health-check:
name: Load Test
steps:
- name: Load Test Execution
uses: http
with:
url: "{{vars.API_URL}}/load-test"
method: POST
body: |
{
"concurrent_users": {{vars.CONCURRENT_REQUESTS}},
"duration_seconds": {{vars.TEST_DURATION}}
}
test: res.code == 200 && res.body.json.success_rate > 0.95
outputs:
success_rate: res.body.json.success_rate
avg_response_time: res.body.json.avg_response_time
使用方法:
# 通常の監視
probe base-config.yml,production-env.yml
# デバッグモード
probe base-config.yml,production-env.yml,debug-overrides.yml
# ロードテスト
probe base-config.yml,production-env.yml,load-test-overrides.yml
2. 環境変数を使った条件付きマージ
環境変数を使用してどのファイルをマージするかを制御します:
conditional-merge.sh:
#!/bin/bash
BASE_FILES="foundation.yml,core-services.yml"
ENV_FILE="${ENVIRONMENT:-development}.yml"
FEATURE_FILES=""
# 環境変数に基づいて機能を追加
if [ "$INCLUDE_SECURITY" = "true" ]; then
FEATURE_FILES="${FEATURE_FILES},security-tests.yml"
fi
if [ "$INCLUDE_PERFORMANCE" = "true" ]; then
FEATURE_FILES="${FEATURE_FILES},performance-tests.yml"
fi
if [ "$INCLUDE_INTEGRATION" = "true" ]; then
FEATURE_FILES="${FEATURE_FILES},integration-tests.yml"
fi
# 最終ファイルリストを構築
FILES="${BASE_FILES},${ENV_FILE}${FEATURE_FILES}"
echo "Executing: probe $FILES"
probe $FILES
使用方法:
# 基本的な監視
ENVIRONMENT=production ./conditional-merge.sh
# セキュリティテスト付き
ENVIRONMENT=production INCLUDE_SECURITY=true ./conditional-merge.sh
# 完全スイート
ENVIRONMENT=production INCLUDE_SECURITY=true INCLUDE_PERFORMANCE=true INCLUDE_INTEGRATION=true ./conditional-merge.sh
3. テンプレートベースの設定
マージによって完成されるテンプレートを使用します:
template-workflow.yml:
name: "{{WORKFLOW_NAME || 'Default Workflow'}}"
description: "{{WORKFLOW_DESCRIPTION || 'Template-based workflow'}}"
vars:
SERVICE_NAME: "{{SERVICE_NAME}}"
ENVIRONMENT: "{{ENVIRONMENT}}"
defaults:
http:
timeout: "{{DEFAULT_TIMEOUT || '30s'}}"
headers:
X-Service: "{{SERVICE_NAME}}"
X-Environment: "{{ENVIRONMENT}}"
jobs:
health-check:
name: "{{SERVICE_NAME}} Health Check"
steps:
- name: Health Endpoint
uses: http
with:
url: "{{vars.SERVICE_URL}}/health"
test: res.code == 200
service-config.yml:
vars:
WORKFLOW_NAME: User Service Monitoring
WORKFLOW_DESCRIPTION: Comprehensive monitoring for the user service
SERVICE_NAME: user-service
SERVICE_URL: https://users.api.company.com
ENVIRONMENT: production
DEFAULT_TIMEOUT: 15s
jobs:
# サービス固有のテストを追加
user-specific-tests:
name: User Service Specific Tests
needs: [health-check]
steps:
- name: User Count Check
uses: http
with:
url: "{{vars.SERVICE_URL}}/users/count"
test: res.code == 200 && res.body.json.count >= 0
- name: User Authentication Test
uses: http
with:
url: "{{vars.SERVICE_URL}}/auth/health"
test: res.code == 200
設定管理パターン
1. 階層設定
継承のための階層で設定を整理します:
configs/
├── base/
│ ├── foundation.yml
│ └── common-defaults.yml
├── services/
│ ├── user-service.yml
│ ├── order-service.yml
│ └── notification-service.yml
├── environments/
│ ├── development.yml
│ ├── staging.yml
│ └── production.yml
└── features/
├── security.yml
├── performance.yml
└── integration.yml
設定管理用 Makefile:
# 基本設定
BASE_CONFIG = configs/base/foundation.yml,configs/base/common-defaults.yml
# 環境固有設定
dev: $(BASE_CONFIG),configs/environments/development.yml
probe $^
staging: $(BASE_CONFIG),configs/environments/staging.yml,configs/features/security.yml
probe $^
prod: $(BASE_CONFIG),configs/environments/production.yml,configs/features/security.yml,configs/features/performance.yml
probe $^
# サービス固有テスト
test-user-service: $(BASE_CONFIG),configs/services/user-service.yml,configs/environments/$(ENV).yml
probe $^
test-all-services: $(BASE_CONFIG),configs/services/user-service.yml,configs/services/order-service.yml,configs/services/notification-service.yml,configs/environments/$(ENV).yml
probe $^
2. 設定検証
実行前にマージ済み設定を検証します:
validation-config.yml:
name: Configuration Validation
description: Validate that required configuration is present
jobs:
config-validation:
name: Configuration Validation
steps:
- name: Validate Required Environment Variables
echo: |
Configuration Validation:
Required Variables:
API_URL: {{vars.API_URL ? "✅ Set" : "❌ Missing"}}
DB_URL: {{vars.DB_URL ? "✅ Set" : "❌ Missing"}}
ENVIRONMENT: {{vars.ENVIRONMENT ? "✅ Set (" + env.ENVIRONMENT + ")" : "❌ Missing"}}
Optional Variables:
SMTP_HOST: {{vars.SMTP_HOST ? "✅ Set" : "⚠️ Not Set"}}
SLACK_WEBHOOK: {{vars.SLACK_WEBHOOK ? "✅ Set" : "⚠️ Not Set"}}
Configuration Status: {{
env.API_URL && env.DB_URL && env.ENVIRONMENT ? "✅ Valid" : "❌ Invalid"
}}
- name: Validate Configuration Consistency
echo: |
Configuration Consistency Check:
Environment Alignment:
{{vars.ENVIRONMENT == "production" && env.API_URL.contains("prod") ? "✅ Production URLs match environment" : ""}}
{{vars.ENVIRONMENT == "staging" && env.API_URL.contains("staging") ? "✅ Staging URLs match environment" : ""}}
{{vars.ENVIRONMENT == "development" && (env.API_URL.contains("localhost") || env.API_URL.contains("dev")) ? "✅ Development URLs match environment" : ""}}
Security Check:
{{vars.ENVIRONMENT == "production" && env.API_URL.startsWith("https://") ? "✅ Production uses HTTPS" : ""}}
{{vars.ENVIRONMENT != "production" || env.API_URL.startsWith("https://") ? "" : "⚠️ Production should use HTTPS"}}
検証付きの使用方法:
# メインワークフロー実行前に設定を検証
probe validation-config.yml,base-config.yml,production.yml && \
probe base-workflow.yml,production.yml
ベストプラクティス
1. ファイル整理
# 良い例: 論理的なファイル整理
# base.yml - コアワークフロー構造
# environment.yml - 環境固有変数
# features.yml - オプション機能追加
# 避ける: すべてを処理しようとするモノリシックファイル
2. 明確なマージ順序
# 良い例: 論理的なマージ順序(一般的なものから具体的なものへ)
probe base.yml,environment.yml,team-overrides.yml
# 避ける: 混乱を招くマージ順序
probe overrides.yml,base.yml,environment.yml # オーバーライドが無視される可能性
3. 環境変数戦略
# 良い例: 動的な値に環境変数を使用
vars:
API_URL: "{{vars.EXTERNAL_API_URL}}"
TIMEOUT: "{{vars.REQUEST_TIMEOUT || '30s'}}"
# 良い例: 基本設定でデフォルトを提供
vars:
DEFAULT_TIMEOUT: 30s
DEFAULT_RETRY_COUNT: 3
4. ドキュメント
# ワークフローにマージ戦略を文書化
name: Multi-Environment API Test
description: |
このワークフローはファイルマージによって複数環境をサポートします。
使用方法:
- 開発環境: probe workflow.yml,development.yml
- ステージング環境: probe workflow.yml,staging.yml
- プロダクション環境: probe workflow.yml,production.yml
ベース workflow.yml がコア構造を提供し、環境ファイルが環境固有の
URL、タイムアウト、認証情報を提供します。
5. マージ検証
jobs:
pre-execution-check:
name: Pre-execution Validation
steps:
- name: Validate Merged Configuration
echo: |
Merged Configuration Summary:
Environment: {{vars.ENVIRONMENT || "Not specified"}}
API URL: {{vars.API_URL || "Not configured"}}
Timeout: {{defaults.http.timeout || "Default"}}
Required configurations: {{
env.API_URL && env.ENVIRONMENT ? "✅ Present" : "❌ Missing"
}}
よくあるアンチパターン
1. 循環依存
# 避ける: 相互に依存するファイル
# base.yml は production.yml でのみ動作する参照を含む
# production.yml は base.yml でのみ動作するジョブを含む
2. 深いオーバーライド階層
# 避ける: オーバーライドレイヤーが多すぎる
probe base.yml,region.yml,environment.yml,team.yml,user.yml,local.yml
# 最終設定がどうなるかを理解することが困難
3. 一貫性のないマージ戦略
# 避ける: 異なるマージアプローチの混在
# あるファイルは完全に上書き、他のファイルは加算的にマージ
# 予測できない結果を生成
次のステップ
ファイルマージを理解したら、以下を探索してください:
ファイルマージは、柔軟で保守しやすいワークフロー設定を構築するための鍵です。これらのパターンをマスターして、ニーズに応じてスケールする再利用可能で環境対応の自動化を作成しましょう。