---
# System prepended metadata

title: Deploy de Projetos com GitHub Actions

---

# 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:


![](https://i.imgur.com/zUirRr9.png)

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.

![](https://i.imgur.com/OvMbcPU.png)


## 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".

![](https://i.imgur.com/xgebrVG.png)


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.
