Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/add workflow for cd #2

Merged
merged 3 commits into from
Jan 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# CIチェックが通ること確認した上で、Rails, Next を自動デプロイ
name: Continuous Delivery

# 当 workflow 実行タイミング
# main ブランチにコード差分が push されたときのみ
on:
push:
branches: [ "main" ]

# 当 workflow 内で使用できる変数を定義
# $AWS_REGION のような形で参照可能
env:
AWS_REGION: us-east-1
ECS_CLUSTER: zenn-clone-cluster
ECS_SERVICE_BACKEND: zenn-clone-backend-service
ECS_SERVICE_FRONTEND: zenn-clone-frontend-service
ECS_TASK_DEFINITION_BACKEND: ./rails/task-definition.json
ECS_TASK_DEFINITION_FRONTEND: ./next/task-definition.json
ECR_REPOSITORY_RAILS: zenn-clone-rails
ECR_REPOSITORY_NEXT: zenn-clone-next
CONTAINER_NAME_RAILS: rails
CONTAINER_NAME_NEXT: next

# ECR push するための権限設定
permissions:
contents: read

# 当 workflow が行う処理
jobs:
# 処理① ci.yml によるチェック
ci:
uses: ./.github/workflows/ci.yml
# 処理② Railsの自動デプロイ。動作には ci のクリアが必要
deploy-rails:
needs: [ci]
runs-on: ubuntu-latest
environment: production

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1

- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY_RAILS:$IMAGE_TAG -f ./rails/Dockerfile.prod ./rails
docker push $ECR_REGISTRY/$ECR_REPOSITORY_RAILS:$IMAGE_TAG
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY_RAILS:$IMAGE_TAG" >> $GITHUB_OUTPUT

- name: Fill in the new image ID in the Amazon ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: ${{ env.ECS_TASK_DEFINITION_BACKEND }}
container-name: ${{ env.CONTAINER_NAME_RAILS }}
image: ${{ steps.build-image.outputs.image }}

- name: Deploy Amazon ECS task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: ${{ env.ECS_SERVICE_BACKEND }}
cluster: ${{ env.ECS_CLUSTER }}
wait-for-service-stability: true
# 処理③ Railsの自動デプロイ。動作には ci のクリアが必要
deploy-next:
needs: [ci]
runs-on: ubuntu-latest
environment: production

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1

- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY_NEXT:$IMAGE_TAG -f ./next/Dockerfile.prod ./next
docker push $ECR_REGISTRY/$ECR_REPOSITORY_NEXT:$IMAGE_TAG
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY_NEXT:$IMAGE_TAG" >> $GITHUB_OUTPUT

- name: Fill in the new image ID in the Amazon ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: ${{ env.ECS_TASK_DEFINITION_FRONTEND }}
container-name: ${{ env.CONTAINER_NAME_NEXT }}
image: ${{ steps.build-image.outputs.image }}

- name: Deploy Amazon ECS task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: ${{ env.ECS_SERVICE_FRONTEND }}
cluster: ${{ env.ECS_CLUSTER }}
wait-for-service-stability: true
53 changes: 53 additions & 0 deletions next/task-definition.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"family": "zenn-clone-task-definition-frontend",
"containerDefinitions": [
{
"name": "next",
"image": "667785573706.dkr.ecr.us-east-1.amazonaws.com/zenn-clone-next:latest",
"cpu": 0,
"portMappings": [
{
"name": "next-80-tcp",
"containerPort": 80,
"hostPort": 80,
"protocol": "tcp",
"appProtocol": "http"
}
],
"essential": true,
"environment": [],
"environmentFiles": [],
"mountPoints": [],
"volumesFrom": [],
"ulimits": [],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/zenn-clone-task-definition-frontend",
"mode": "non-blocking",
"awslogs-create-group": "true",
"max-buffer-size": "25m",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs"
},
"secretOptions": []
},
"systemControls": []
}
],
"taskRoleArn": "arn:aws:iam::667785573706:role/ecsTaskExecutionRole",
"executionRoleArn": "arn:aws:iam::667785573706:role/ecsTaskExecutionRole",
"networkMode": "awsvpc",
"volumes": [],
"placementConstraints": [],
"requiresCompatibilities": [
"FARGATE"
],
"cpu": "256",
"memory": "512",
"runtimePlatform": {
"cpuArchitecture": "X86_64",
"operatingSystemFamily": "LINUX"
},
"enableFaultInjection": false
}
174 changes: 174 additions & 0 deletions rails/task-definition.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
{
"taskDefinitionArn": "arn:aws:ecs:us-east-1:667785573706:task-definition/zenn-clone-task-definition-backend:10",
"containerDefinitions": [
{
"name": "rails",
"image": "667785573706.dkr.ecr.us-east-1.amazonaws.com/zenn-clone-rails",
"cpu": 0,
"portMappings": [
{
"name": "rails-3000-tcp",
"containerPort": 3000,
"hostPort": 3000,
"protocol": "tcp",
"appProtocol": "http"
}
],
"essential": true,
"environment": [
{
"name": "RAILS_MASTER_KEY",
"value": "baa4eee02f9c7fc3a88c9f113fb2ee53"
},
{
"name": "RAILS_LOG_TO_STDOUT",
"value": "true"
}
],
"environmentFiles": [],
"mountPoints": [],
"volumesFrom": [],
"ulimits": [],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/zenn-clone-task-definition-backend",
"mode": "non-blocking",
"awslogs-create-group": "true",
"max-buffer-size": "25m",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs"
},
"secretOptions": []
},
"healthCheck": {
"command": [
"CMD-SHELL",
"curl --unix-socket /myapp/tmp/sockets/puma.sock localhost/api/v1/health_check || exit 1"
],
"interval": 30,
"timeout": 5,
"retries": 3
},
"systemControls": []
},
{
"name": "nginx",
"image": "667785573706.dkr.ecr.us-east-1.amazonaws.com/zenn-clone-nginx",
"cpu": 0,
"portMappings": [
{
"name": "nginx-80-tcp",
"containerPort": 80,
"hostPort": 80,
"protocol": "tcp",
"appProtocol": "http"
}
],
"essential": true,
"environment": [],
"environmentFiles": [],
"mountPoints": [],
"volumesFrom": [
{
"sourceContainer": "rails",
"readOnly": false
}
],
"dependsOn": [
{
"containerName": "rails",
"condition": "HEALTHY"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/zenn-clone-task-definition-backend",
"mode": "non-blocking",
"awslogs-create-group": "true",
"max-buffer-size": "25m",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs"
},
"secretOptions": []
},
"healthCheck": {
"command": [
"CMD-SHELL",
"curl -f http://localhost/api/v1/health_check || exit 1"
],
"interval": 30,
"timeout": 5,
"retries": 3
},
"systemControls": []
}
],
"family": "zenn-clone-task-definition-backend",
"taskRoleArn": "arn:aws:iam::667785573706:role/ecsTaskExecutionRole",
"executionRoleArn": "arn:aws:iam::667785573706:role/ecsTaskExecutionRole",
"networkMode": "awsvpc",
"revision": 10,
"volumes": [],
"status": "ACTIVE",
"requiresAttributes": [
{
"name": "ecs.capability.execution-role-awslogs"
},
{
"name": "com.amazonaws.ecs.capability.ecr-auth"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.28"
},
{
"name": "com.amazonaws.ecs.capability.task-iam-role"
},
{
"name": "ecs.capability.container-health-check"
},
{
"name": "ecs.capability.execution-role-ecr-pull"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.18"
},
{
"name": "ecs.capability.task-eni"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.29"
},
{
"name": "com.amazonaws.ecs.capability.logging-driver.awslogs"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.24"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.19"
},
{
"name": "ecs.capability.container-ordering"
}
],
"placementConstraints": [],
"compatibilities": [
"EC2",
"FARGATE"
],
"requiresCompatibilities": [
"FARGATE"
],
"cpu": "256",
"memory": "512",
"runtimePlatform": {
"cpuArchitecture": "X86_64",
"operatingSystemFamily": "LINUX"
},
"registeredAt": "2025-01-09T02:12:49.753Z",
"registeredBy": "arn:aws:iam::667785573706:root",
"enableFaultInjection": false,
"tags": []
}
Loading