# Deploy de Projetos com GitHub Actions
> [name=Vinicius Roberto Martins] [time=Thu, Apr 9, 2020 11:05 AM]
Este documento explica como é realizar o deploy em um serviço Amazon ECS utilizando Continuous Integration com Workflows do GitHub Actions.
O conteúdo deste docimento poderá ser alterado a qualquer momento de acordo com a necessidade de melhorias e otimizações no processo. Estamos sempre abertos a novas ideias e soluções!
---
[TOC]
## Get Started
O ponto de partida é ter um repositório do projeto no GitHub, o qual será atualizado e cada modificação atribuida a *branch master* acionará o workflow.
Então, vamos ao repositório!
Inicialmente você terá uma estrutura de arquivos como esta:

Então incluiremos alguns arquivos que serão fundamentais para o processo de deploy. Para isto, primeiro sincronize o repositório local com o remotoj, utilizando o comando abaixo em seu terminal.
```shell
$ git pull https://github.com/user/repositorio.git
```
### Arquivos
#### dockerfile
O dockerfile é um arquivo que contém instruções para gerar a imagem que será utilizada para criar o container. Na raiz do projeto crie um arquivo com o nome `dockerfile`, e insira o código abaixo.
> Este dockerfile irá criar uma imagem com o PHP7.3 + Laravel.
```dockerfile=
FROM ubuntu:18.04
RUN apt update
RUN apt -y install software-properties-common
RUN add-apt-repository ppa:ondrej/php
RUN apt update
WORKDIR /var/www
COPY . .
RUN apt install nginx -y
RUN service nginx start
RUN chown www-data:www-data /var/www/public -R
RUN chmod 777 /var/www/database -R
RUN chmod 777 /var/www/storage -R
ENV DEBIAN_FRONTEND=noninteractive
RUN apt -y install php7.3-fpm php7.3-mysql php-common \
php7.3-cli php7.3-common php7.3-json php7.3-opcache \
php7.3-readline php7.3-mbstring php7.3-xml php7.3-gd php7.3-curl
RUN service php7.3-fpm start
RUN apt -y install git && apt -y install curl && apt -y install zip
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
RUN rm /etc/nginx/sites-enabled/default
ADD vhost.conf /etc/nginx/conf.d/default.conf
RUN apt install python-setuptools -y \
&& apt -y install python-pip \
&& pip install supervisor
COPY supervisord.conf /etc/
RUN chmod +x /etc/supervisord.conf
COPY run.sh /
RUN chmod +x /run.sh
ENTRYPOINT ["sh", "/run.sh"]
RUN composer install
```
#### vhost.conf
Configuração do arquivo Virtual Host do Nginx para para determinar qual site será solicitado.
```conf=
server {
listen 80;
root /var/www/public/;
index index.php index.html index.htm index.nginx-debian.html;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php7.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
include snippets/fastcgi-php.conf;
}
# A long browser cache lifetime can speed up repeat visits to your page
location ~* \.(jpg|jpeg|gif|png|webp|svg|woff|woff2|ttf|css|js|ico|xml)$ {
access_log off;
log_not_found off;
expires 360d;
}
# disable access to hidden files
location ~ /\.ht {
access_log off;
log_not_found off;
deny all;
}
}
```
#### supervisor.conf
O supervisor.conf é o arquivo de configuração do "Supervisor", aplicação que controla a inicialização de processos em um sistema UNIX. Neste caso definimos o PHP7.3 e o Nginx para serem inicilializados junto com o SO.
```conf=
[supervisord]
nodaemon=false
[program:php-fpm7.3]
command=/usr/sbin/php-fpm7.3
[program:nginx]
command=/usr/sbin/nginx
```
#### run.sh
Este scrip é para inicializar o Supervisor.
```sh=
#!/bin/bash
/usr/local/bin/supervisord -c /etc/supervisord.conf
/bin/bash
```
#### task-definition.json
Agora incluiremos o arquivo de `task-definition.json` o qual contém informações que definarão o container e como ele será construído, de acordo com o projeto em questão.
> Os valores que estão como "projeto" e somente eles, deverão ser anterados para o nome do projeto em questão.
```json=
{
"family": "ecos-projeto",
"containerDefinitions": [
{
"name": "ecos-projeto",
"memory": 150,
"image": "779863683866.dkr.ecr.us-west-2.amazonaws.com/php7.3-laravel",
"portMappings": [
{
"containerPort": 80,
"hostPort": 0,
"protocol": "tcp"
}
],
"interactive": true,
"essential": true,
"command": [],
"dockerLabels": {
"traefik.frontend.rule": "Host:projeto.com.br,www.projeto.com.br",
"traefik.enable": "true",
"traefik.backend": "projeto-backend",
"traefik.port": ""
}
}
],
"requiresCompatibilities": [
"EC2"
]
}
```
#### .dockerignore
Adicione o arquivo `.dockerignore`. Há arquivos e diretórios que não precisamos que sejam incluídos no contexto de build da imagem.
```dockerfile=
dockerfile
.git
.github
task-definition.json
*.md
!README*.md
README-secret.md
.cache
```
Após inserir todos os arquivos, seu diretório do projeto terá uma estrutura como esta.

## Criando o Workflow
> É necessário criar previamente o repositório para imagem do projeto no AWS ECR, pois será o qual, durante o processo do workflow, receberá a imagem "buildada"
Agora, este é procedimento que faz a "mágica" acontecer, iremos configurar o workflow. No repositório do projeto no GitHub, clique na opção "Action", e procure por "Deploy to Amazon ECS".

Em seguida clique em "Set up this workflow". Será gerado um arquivo `aws.yml`, o qual contêm os procedimentos que serão realizados para o processo de deploy. Substitua pelo conteúdo abaixo.
```yml
on:
push:
branches:
- master
name: Deploy to Amazon ECS
jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- 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: us-west-2
- 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 }}
ECR_REPOSITORY: projeto
IMAGE_TAG: ${{ github.sha }}
run: |
# Build a docker container and
# push it to ECR so that it can
# be deployed to ECS.
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"
- 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: task-definition.json
container-name: ecos-projeto
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: ecos-projeto
cluster: ecos
wait-for-service-stability: true
```
Será necessário a modificação de valores pelo nome do projeto, em:
* ECR_REPOSITORY
* container-name
* service
Como pode ser observado em aws-access-key-id e aws-secret-access-key são tratados com variáveis de ambiente, então é necessário solicitar ao Admin da conta do GitHub do Grupo, para que insira os valores e respectivas chaves como variáveis, na aba "Settings" do repositório.
Após realizar todas as modificações clique em "Start commit" para confirmar a configuração do workflow.
## Push to GitHub
Agora com todos os arquivos já incluídos no projeto, realize o commit e enviei para o repositório.
```shell
$ git push -u origin branch
```
Com isso, caso o push tenha sido realizado na master já irá acionar o workflow da action, que realizará o deploy. Caso tenha feito o push em uma branch dev, por exemplo, é só gerar o pull request para mergear a branch dev na master, assim acionará automaticamente o workflow.
Com isso concluímos nossa configuração de CI!
> O procedimento de gerar o Certificado e inceri-lo no Load Balancer, e configuração do AWS Route53 devem ser realizados normalmente.