目指すところ
ブランチを作成するとgoogle認証付きドメインが自動 or 手動でデプロイされる
feature-1111 ブランチが作成される
ビルドが走って、feature-1111 コンテナが起動する
feature-1111.hoge.example.com ドメインにアクセスすると google 認証でログインして確認できる
追加の要件で開発環境用の設定が3種類あり指定できるようにする (この条件があるのでbotでの手動手順で)
前提条件
- *.hoge.example.com ドメインの特定albへの関連付け
- *.hoge.example.com を受け付けるalbでのcognito設定
- docker入りEC2インスタンスひとつ
- 環境 aaa, bbb, ccc のどれかを指定してデプロイできるようにする
Dockerの環境について
docker入りEC2インスタンスには同一ネットワークを使い回せるようしたproxyコンテナ準備しておく
ブランチ名.hoge.example.com を ブランチ名コンテナにわたす設定を入れる
version: '3'
services:
nginx:
container_name: "proxy-branches"
hostname: "proxy-branches"
image: nginx:1.17.4
environment:
- TZ=Asia/Tokyo
ports:
- 80:80
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf
networks:
- branch_local
networks:
branch_local:
external: true
- default.conf
server {
listen 80;
server_name _;
resolver 127.0.0.11;
real_ip_header X-Forwarded-For;
set_real_ip_from 0.0.0.0/0;
real_ip_recursive on;
client_max_body_size 20M;
location / {
set $container $host;
if ($host ~ ^(.*)\.hoge\.example\.com) { set $container $1; }
proxy_pass http://$container;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
ブランチごとに作成するコンテナのテンプレート例
version: '3'
services:
nginx:
container_name: "{{DIRENV}}"
hostname: "{{DIRENV}}"
image: nginx:1.17.4
environment:
- TZ=Asia/Tokyo
volumes:
- /var/www/{{DIRENV}}:/var/www/html
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf
networks:
- branch_local
php-fpm:
container_name: "{{DIRENV}}-front-php"
hostname: "{{DIRENV}}-front-php-fpm"
image: my-front-php-fpm:latest
volumes:
- /var/www/{{DIRENV}}:/var/www/html
networks:
- branch_local
networks:
branch_local:
external: true
環境設定ファイル群は扱いやすい場所においておく
Buildspec参照
cognitoを更新するシェルスクリプト例
ALBでgoogle認証をcognitoで使う方法は以下を参照
https://qiita.com/netebakari/items/bdd6930bec1acc4d647f
環境変数でブランチ名を受け取って、該当ドメインをalbに設定したcognitoユーザプールに追加するシェルスクリプト
(code buildに含める)
CognitoPoolId,CognitoClientId はAWSコンソールを参照
AddURL="https://${BRANCH}.hoge.example.com/oauth2/idpresponse"
AWS_REGION=ap-northeast-1
ExistingCallbackUrls=$(aws cognito-idp describe-user-pool-client --user-pool-id $CognitoPoolId --client-id $CognitoClientId --region $AWS_REGION | jq -r '.UserPoolClient.CallbackURLs|join(" ")' | sed 's/,/ /g')
NewCallbackUrls="$ExistingCallbackUrls $AddURL"
aws cognito-idp update-user-pool-client --user-pool-id $CognitoPoolId --client-id $CognitoClientId --callback-urls $NewCallbackUrls --supported-identity-providers "Google" --allowed-o-auth-flows "code" --allowed-o-auth-scopes "email" "openid" "profile" --allowed-o-auth-flows-user-pool-client --region $AWS_REGION
echo $SourceVariables
aws cognito-idp がオプションなしupdateを実行すると、すでに入っている設定を維持しないことに注意
オプションを付けないと設定がなくなる.
Buildspec例(code build)
環境変数にDIRENV(ブランチ名->ディレクトリ名)、DEVENV(環境名aaa|bbb|ccc)、DOMAIN(ブランチ名->小文字化したドメイン名)
CognitoPoolId、CognitoClientId を入れる
version: 0.2
phases:
install:
runtime-versions:
nodejs: 10
build:
commands:
- curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.0/install.sh | bash ; export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")" ; [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" ;nvm install v11.11.1
- npm ci
- npm start
- rm bin/build.sh
- sed -i -e "s/755/777/g" appspec.yml
- sed -i -e "s@/var/www/html/hoge@/var/www/${DOMAIN}/hoge@g" appspec.yml
- echo '#!/usr/bin/env bash' > bin/build.sh
- echo "docker run --rm -v /var/www/${DOMAIN}/hoge:/var/www/html/hoge front-php-fpm-infra sh -c 'cd /var/www/html/hoge && /usr/local/bin/composer install'" >> bin/build.sh
- echo "cp -pR /home/hoge/template /home/hoge/dev-branches/${DOMAIN} && cd /home/hoge/dev-branches/${DOMAIN} && sed -e \"s/{{DIRENV}}/${DOMAIN}/\" docker-compose.template > docker-compose.yml && sed -i -e \"s/{{DIRENV}}/${DOMAIN}/\" nginx/conf.d/default.conf && docker-compose up -d" >> bin/build.sh
- echo "docker exec ${DOMAIN}-front-php sh -c 'cd /var/www/html/hoge && php init --env=Development --overwrite=All && chmod -R 777 /var/www/html/hoge'" >> bin/build.sh
- echo "cp ../../template/${DEVENV}/hoge/common/config/* /var/www/${DOMAIN}/hoge/common/config/" >> bin/build.sh
- echo "cp ../../template/${DEVENV}/hoge/frontend/config/* /var/www/${DOMAIN}/hoge/frontend/config/" >> bin/build.sh
- AddURL="https://${DOMAIN}.hoge.example.com/oauth2/idpresponse"
- AWS_REGION=ap-northeast-1
- ExistingCallbackUrls=$(aws cognito-idp describe-user-pool-client --user-pool-id $CognitoPoolId --client-id $CognitoClientId --region $AWS_REGION | jq -r '.UserPoolClient.CallbackURLs|join(" ")' | sed 's/,/ /g')
- NewCallbackUrls="$ExistingCallbackUrls $AddURL"
- aws cognito-idp update-user-pool-client --user-pool-id $CognitoPoolId --client-id $CognitoClientId --callback-urls $NewCallbackUrls --supported-identity-providers "Google" --allowed-o-auth-flows "code" --allowed-o-auth-scopes "email" "openid" "profile" --allowed-o-auth-flows-user-pool-client --region $AWS_REGION
- echo $SourceVariables
artifacts:
files:
- '**/*'
CodePipeline設定jsonの作成
code-pipelineでSource GitHub, Build AWS CodeBuild, Deploy AWS CodeDeploy でとりあえずmasterがデプロイできる環境を設定する
下準備として作成したcode-pipeline設定を読み取ってmetadataを消す
(code-pipelineの設定をjsonで書いてもいいけど大変なのでAWSコンソールで作って読み込んでファイルに出す)
aws codepipeline get-pipeline --name MyFirstPipeline > branches-deploy.json
ブランチが作られるごとに毎回環境が必要ではなかったので
botでのブランチ環境作成としているが
ブランチ毎、プルリク毎の場合はgithubのフック等で叩く
cognitoにドメインを登録するときに大文字が入ると動作しないのでドメインのみ小文字化する
python-slackbot 例
# -*- coding: utf-8 -*
from slackbot.bot import respond_to
from slackbot.bot import listen_to
from slackbot.bot import default_reply
import subprocess
import re
@listen_to('deploy-branch\s*(.*)\s(.*)')
def mention_func1(message, arg1, arg2):
AWS_COMMAND = "/usr/local/bin/aws"
BRANCH = arg1
DEVENV = arg2
DOMAIN = str.lower(arg1)
if DEVENV in ["aaa", "bbb", "ccc"]:
subprocess.run('sed -e "s/{{BRANCH}}/' + BRANCH + '/g" branches-deploy-template.json > branches-deploy.json', shell = True, stdout = subprocess.PIPE, cwd = '/slackbot/plugins')
subprocess.run('sed -i -e "s/{{DEVENV}}/' + DEVENV + '/g" branches-deploy.json', shell = True, stdout = subprocess.PIPE, cwd = '/slackbot/plugins')
subprocess.run('sed -i -e "s/{{DOMAIN}}/' + DOMAIN + '/g" branches-deploy.json', shell = True, stdout = subprocess.PIPE, cwd = '/slackbot/plugins')
subprocess.run('aws codepipeline update-pipeline --cli-input-json file://branches-deploy.json', shell = True, stdout = subprocess.PIPE, cwd = '/slackbot/plugins')
subprocess.run('aws deploy create-deployment-group --application-name ec2docker-branch --ec2-tag-filters Key=Name,Type=KEY_AND_VALUE,Value=instance-name --deployment-group-name ec2docker-branch-group-' + DOMAIN + ' --service-role-arn arn:aws:iam::XXXXXXXXXX:role/dev-deploy-role', shell = True, stdout = subprocess.PIPE, cwd = '/slackbot/plugins')
subprocess.run('aws codepipeline start-pipeline-execution --name branches-deploy --region ap-northeast-1', shell = True, stdout = subprocess.PIPE, cwd = '/slackbot/plugins')
message.send("https://" + DOMAIN + ".hoge.example.com/ を作成するデプロイを開始しました")
else:
message.send("第2引数の環境の指定はaaa,bbb,cccだけです")
使い方
botのいるところで
deploy-branch feature-1111 aaa