Este tutorial explica como funciona o schema do GitHub Actions, com foco em erros comuns e melhores práticas. Baseado em experiências reais de debugging.
O schema define regras específicas para escrever workflows YAML. Diferente do YAML comum, o GitHub Actions tem sintaxe própria para certas funcionalidades.
# ❌ YAML válido, mas ERRO no GitHub Actions
if: "always() && !contains(github.event.head_commit.message, 'chore(release)')"
# ✅ Correto no GitHub Actions
if: always() && !contains(github.event.head_commit.message, 'chore(release)')- Não use aspas em expressões com funções
- Aspas só para strings literais
- Funções como
always(),contains(),startsWith()não precisam de aspas
# Funções sem aspas
if: always()
if: contains(github.event.head_commit.message, 'fix')
if: startsWith(github.event.ref, 'refs/tags/')
# Combinações
if: always() && !contains(github.event.head_commit.message, 'chore(release)')
if: github.event_name == 'pull_request' && github.event.action == 'opened'
# Com variáveis
if: needs.test-job.outputs.success == 'true'# Aspas desnecessárias
if: "always()"
if: "contains(github.event.head_commit.message, 'fix')"
# Aspas em combinações (QUEBRAM tudo)
if: "always() && !contains(github.event.head_commit.message, 'chore(release)')"- GitHub Actions trata aspas como strings literais
"always()"vira uma string, não uma função- O parser espera uma expressão booleana, não uma string
jobs:
job-a:
runs-on: ubuntu-latest
steps:
- run: echo "Job A"
job-b:
needs: job-a # ✅ Correto: referência simples
if: needs.job-a.result == 'success' # ✅ Correto: expressão
runs-on: ubuntu-latestjobs:
test:
outputs:
code-changed: ${{ steps.filter.outputs.code }}
steps:
- id: filter
run: echo "code=true" >> $GITHUB_OUTPUT
deploy:
needs: test
if: needs.test.outputs.code-changed == 'true' # ✅ Correto
runs-on: ubuntu-latestgithub.*- Informações do eventoenv.*- Variáveis de ambientevars.*- Variáveis do repositóriosecrets.*- Segredosneeds.*- Outputs de jobssteps.*- Outputs de steps
# Contexto github
if: github.event_name == 'pull_request'
if: github.base_ref == 'main'
# Contexto needs
if: needs.build.result == 'success'
# Contexto env
if: env.NODE_ENV == 'production'-
Sintaxe YAML básica
pnpm lint:yaml
-
Validação de estrutura
python3 -c "import yaml; yaml.safe_load(open('workflow.yml'))" -
Teste de expressões
- Verifique condições
ifsem aspas - Teste funções uma por vez
- Use
always()para debug
- Verifique condições
-
Validação no GitHub
- Push e veja se workflow roda
- Verifique logs de erro específicos
| Erro | Causa | Solução |
|---|---|---|
Unexpected symbol: '"always' |
Aspas em funções | Remova aspas |
needs.job-a.outputs is not defined |
Job não tem outputs | Defina outputs no job |
contains is not defined |
Função não reconhecida | Use contains() sem aspas |
| Workflow não dispara | Problema no on: |
Verifique triggers |
# Comece simples
if: always()
# Adicione complexidade gradualmente
if: always() && github.event_name == 'push'
# Teste final
if: always() && !contains(github.event.head_commit.message, 'skip')steps:
- id: test
run: echo "success=true" >> $GITHUB_OUTPUT
- name: Deploy
if: steps.test.outputs.success == 'true'
run: echo "Deploying..."- Use
pnpm lint:yamlantes de commitar - Teste workflows em branches separadas
- Leia logs de erro com atenção
# ❌ Sem comentário
if: always() && !contains(github.event.head_commit.message, 'chore(release)')
# ✅ Com explicação
# Sempre rode, mas pule se for commit de release automático
if: always() && !contains(github.event.head_commit.message, 'chore(release)')O schema do GitHub Actions é poderoso mas rigoroso. Os erros mais comuns vêm de:
- Aspas desnecessárias em condições
if - Sintaxe incorreta de funções
- Referências erradas a contextos
Lembre-se: Debugging sistemático > Tentativa e erro!
Baseado em experiências reais de debugging de workflows complexos.