Tutorial Completo GitHub Actions 🤖

CI/CD com
GitHub Actions

Do primeiro workflow ao pipeline completo — automatize testes, build e deploy direto no GitHub com exemplos reais.

📦 checkout
🔧 install
🧪 test
🏗️ build
🚀 deploy
12 Módulos
5 Conceitos-chave
YAML Formato
workflow jobs / steps secrets matrix cache deploy
01

⚙️ O que é GitHub Actions?

O GitHub Actions é uma plataforma de CI/CD (Integração Contínua / Entrega Contínua) integrada ao GitHub — permite automatizar tarefas diretamente no repositório.

🧪

Rodar testes automaticamente

🏗️

Buildar o projeto a cada push

🚀

Deploy automático para produção

🤖

Executar scripts e automações

🧠
CI (Integração Contínua) — roda testes toda vez que há um push, detectando erros cedo.
CD (Entrega Contínua) — automatiza o deploy para staging ou produção após os testes passarem.
02

📦 Conceitos fundamentais

📄 Workflow

Arquivo .yml que define toda a automação. Fica em .github/workflows/.

⚡ Evento (trigger)

O que dispara o workflow: push, pull_request, schedule...

🗂️ Job

Conjunto de steps que roda em uma máquina (runner). Jobs podem rodar em paralelo.

🔧 Step

Cada ação dentro de um job — um comando run ou uma action reutilizável.

🖥️ Runner

Máquina virtual que executa o job: ubuntu-latest, windows-latest, macos-latest.

🔑 Secret

Variável sensível (token, senha) armazenada com segurança no GitHub.

Workflow contém um ou mais Jobs
Job contém um ou mais Steps
Step executa um run ou uses
03

📁 Estrutura e primeiro workflow

Os workflows ficam em arquivos .yml dentro de .github/workflows/ na raiz do repositório:

📁 meu-projeto/
  📁 .github/
    📁 workflows/
      📄 ci.yml ← seu workflow aqui
      📄 deploy.yml
  📄 src/
  📄 package.json
primeiro workflow — hello world
name: Meu primeiro workflow

on: [push]

jobs:
  exemplo:
    runs-on: ubuntu-latest

    steps:
      - name: Clonar repositório
        uses: actions/checkout@v4

      - name: Rodar comando
        run: echo "Hello World!"
namenome do workflow (aparece na aba Actions do GitHub)
onevento que dispara o workflow
jobsconjunto de tarefas a executar
runs-onsistema operacional do runner
stepslista de passos do job
usesusa uma action pronta (reutilizável)
runexecuta um comando shell
⚠️
YAML é sensível a indentação! Use sempre 2 espaços — nunca TAB. Um erro de indentação faz o workflow falhar com mensagem confusa.
04

⚡ Eventos (triggers)

O campo on define quando o workflow é executado. Pode ter múltiplos triggers ao mesmo tempo.

push em branch específica
on:
  push:
    branches: [main, develop]
    paths:                    # opcional: só se mudar esses arquivos
      - 'src/**'
      - 'package.json'
pull request
on:
  pull_request:
    branches: [main]
    types: [opened, synchronize, reopened]
manual e agendado
on:
  workflow_dispatch:          # botão manual na aba Actions

  schedule:
    - cron: "0 2 * * *"        # todo dia às 02:00 UTC
    - cron: "0 9 * * 1"        # toda segunda às 09:00 UTC
EventoQuando dispara
pushA cada push em branches configuradas
pull_requestCriação ou atualização de PR
workflow_dispatchManualmente pelo botão na UI do GitHub
scheduleEm horários definidos (cron)
releaseQuando uma release é publicada
workflow_callChamado por outro workflow
05

🔧 Actions prontas (uses)

Actions são blocos reutilizáveis criados pela comunidade — use com uses: owner/action@versão. Encontre em marketplace.github.com.

actions mais usadas
# Essencial — clona o repo (sempre o primeiro step!)
- uses: actions/checkout@v4

# Configura Node.js
- uses: actions/setup-node@v4
  with:
    node-version: 18
    cache: 'npm'               # cache automático do npm

# Configura Python
- uses: actions/setup-python@v5
  with:
    python-version: '3.11'

# Configura PHP
- uses: shivammathur/setup-php@v2
  with:
    php-version: '8.2'

# Cache genérico
- uses: actions/cache@v4

# Upload de artefato
- uses: actions/upload-artifact@v4

# Download de artefato
- uses: actions/download-artifact@v4
💡
Sempre fixe a versão das actions: actions/checkout@v4 em vez de @main. Isso evita quebrar seu pipeline com mudanças inesperadas.
06

🔹 CI para Node.js e PHP

CI completo — Node.js
name: Node CI

on:
  push:
    branches: [main]
  pull_request:

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 18
          cache: 'npm'

      - name: Instalar dependências
        run: npm ci

      - name: Rodar testes
        run: npm test

      - name: Build
        run: npm run build
CI completo — PHP + Composer
name: PHP CI

on: [push, pull_request]

jobs:
  php:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Instalar PHP 8.2
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'
          extensions: mbstring, intl, pdo_mysql
          coverage: none

      - name: Instalar dependências
        run: composer install --no-progress --prefer-dist

      - name: Rodar testes
        run: php artisan test
📌
Use npm ci em vez de npm install em CI — ele é mais rápido e determinístico, instalando exatamente o que está no package-lock.json.
07

🔑 Secrets e variáveis de ambiente

Secrets armazenam dados sensíveis (tokens, senhas, chaves de API) com segurança — nunca aparecem nos logs.

configurar secrets no GitHub
Repositório → Settings → Secrets and variables → Actions → New repository secret

# Exemplos de secrets úteis:
# DEPLOY_KEY       → chave SSH para deploy
# DATABASE_URL     → URL de banco de dados
# API_TOKEN        → token de API externa
# DOCKER_PASSWORD  → senha do Docker Hub
usar secrets e variáveis no workflow
env:
  APP_ENV: production              # variável global do workflow

jobs:
  deploy:
    runs-on: ubuntu-latest
    env:
      DB_HOST: localhost            # variável do job

    steps:
      - name: Deploy
        env:
          TOKEN: ${{ secrets.MEU_TOKEN }}       # secret
          SSH_KEY: ${{ secrets.DEPLOY_KEY }}    # secret
        run: |
          echo "Token: $TOKEN"
          echo "Env: $APP_ENV"
contextos availáveis com ${{ }}
${{ secrets.NOME }}          # secrets do repositório
${{ github.ref }}             # branch/tag atual
${{ github.sha }}             # hash do commit
${{ github.actor }}          # quem fez push
${{ runner.os }}              # sistema operacional
${{ matrix.node }}           # valor da matrix atual
${{ steps.STEP_ID.outputs.NOME }}  # output de step anterior
⚠️
Nunca coloque senhas, tokens ou chaves diretamente no YAML! Use sempre Secrets. O arquivo .yml fica público no repositório.
08

🔹 Matrix e Cache

Matrix — testar em múltiplas versões

Execute o mesmo job em várias combinações de versões ou sistemas automaticamente:

matrix — múltiplas versões Node
jobs:
  test:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node: [16, 18, 20]
        os: [ubuntu-latest, windows-latest]

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}

      - run: npm ci && npm test
💡
Com a matrix acima, o GitHub roda 6 jobs em paralelo (3 versões × 2 sistemas) automaticamente. Perfeito para garantir compatibilidade.

Cache — builds mais rápidos

cache do npm
- name: Cache node_modules
  uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-node-
cache do composer (PHP)
- name: Cache Composer
  uses: actions/cache@v4
  with:
    path: vendor
    key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }}
09

🔹 Jobs dependentes e condições

Use needs para criar dependências entre jobs — o deploy só roda se o build passar:

dependência entre jobs
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm run build

  test:
    needs: build          # só roda após build
    runs-on: ubuntu-latest
    steps:
      - run: npm test

  deploy:
    needs: [build, test]  # só roda após build E test
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploy!"
condições — if
# Job só roda em push na main
deploy:
  if: github.ref == 'refs/heads/main'
  runs-on: ubuntu-latest

# Step só roda se anterior falhar
- name: Notificar falha
  if: failure()
  run: echo "Build falhou!"

# Step só roda em push (não em PR)
- name: Deploy
  if: github.event_name == 'push'
  run: ./deploy.sh
multiline run — vários comandos
- name: Build e test
  run: |
    echo "Instalando..."
    npm ci
    echo "Buildando..."
    npm run build
    echo "Testando..."
    npm test
10

🔹 Artefatos e Docker

Artefatos — compartilhar arquivos entre jobs

upload e download de artefatos
# Job 1: gera o build e faz upload
build:
  steps:
    - run: npm run build

    - uses: actions/upload-artifact@v4
      with:
        name: build-files
        path: dist/
        retention-days: 7

# Job 2: baixa e usa o artefato
deploy:
  needs: build
  steps:
    - uses: actions/download-artifact@v4
      with:
        name: build-files

    - run: ls -la  # arquivos do dist/ disponíveis aqui

Docker no GitHub Actions

build e push de imagem Docker
docker:
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4

    - name: Login no Docker Hub
      uses: docker/login-action@v3
      with:
        username: ${{ secrets.DOCKER_USERNAME }}
        password: ${{ secrets.DOCKER_PASSWORD }}

    - name: Build e push
      uses: docker/build-push-action@v5
      with:
        context: .
        push: true
        tags: meu-usuario/minha-app:latest
11

🔹 Pipeline completo — realista

Um pipeline completo de CI/CD para uma aplicação Node.js — lint, testes, build e deploy:

ci-cd.yml — pipeline completo
name: CI/CD Pipeline

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  NODE_VERSION: '18'

jobs:
  ##──── 1. Lint e testes ────##
  test:
    name: 🧪 Lint & Test
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'

      - run: npm ci
      - run: npm run lint
      - run: npm test

  ##──── 2. Build ────##
  build:
    name: 🏗️ Build
    needs: test
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'

      - run: npm ci && npm run build

      - uses: actions/upload-artifact@v4
        with:
          name: dist
          path: dist/

  ##──── 3. Deploy (só na main) ────##
  deploy:
    name: 🚀 Deploy
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'

    steps:
      - uses: actions/download-artifact@v4
        with:
          name: dist

      - name: Deploy via SSH
        env:
          SSH_KEY: ${{ secrets.DEPLOY_KEY }}
          SSH_HOST: ${{ secrets.SERVER_HOST }}
        run: |
          echo "Deploying to $SSH_HOST..."
          # rsync -avz dist/ user@$SSH_HOST:/var/www/app
12

🔹 Boas práticas e erros comuns

✔ Separe build e deploy

Jobs diferentes, responsabilidades diferentes — mais fácil debugar.

✔ Use cache sempre

Reduz o tempo de build de minutos para segundos em projetos grandes.

✔ Use Secrets

Nunca hardcode senhas, tokens ou chaves no YAML.

✔ Nomeie bem os steps

Facilita identificar onde falhou nos logs da aba Actions.

❌ erros comuns
# ❌ Esquecer o checkout — NADA funciona sem ele!
steps:
  - run: npm test  # o repositório não foi clonado!

# ✅ Checkout SEMPRE como primeiro step
steps:
  - uses: actions/checkout@v4
  - run: npm test

# ❌ Indentação errada (YAML é sensível!)
steps:
    - run: echo "ok"    # 4 espaços em vez de 2 — erro!

# ❌ Não usar cache = builds lentos
# Sempre adicione cache para npm, pip, composer, etc.

# ❌ Segredo hardcoded
run: curl -H "Token: abc123secreto" api.exemplo.com
resumo mental
# Workflow  → arquivo .yml em .github/workflows/
# on        → quando o workflow dispara
# jobs      → tarefas paralelas ou sequenciais
# steps     → comandos dentro de um job
# uses      → action pronta do marketplace
# run       → comando shell
# secrets   → dados sensíveis seguros
# needs     → dependência entre jobs
# matrix    → roda em múltiplas versões
# cache     → acelera o build
🚀
Caminho recomendado: workflow básico → CI para seu stack (Node/PHP) → Secrets → Cache → Deploy → Docker + Actions → Pipelines completos com lint + test + build + deploy.