Pular para o conteúdo principal

victorstein.dev

80/100 Dias de Golang - Mini Servidor de CI/CD – Parte 4 - Adicionando testes ao repositório!

# Mini Servidor de CI/CD – Parte 4: Adicionando testes ao repositório!

Finalizamos a implementação da API e a execução dos pipelines. Agora é hora de garantir que tudo isso funcione como esperado com testes automatizados. Para fazer os testes vamos instalar a go get github.com/stretchr/testify e criar nosso arquivo: internal/api/test/handlers_test.go

Vamos iniciar criando um setup para nossos testes. Para isso vamos criar um banco em memória.

func setupTestRouter() *gin.Engine {
	database, _ := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	db.DB = database
	db.DB.AutoMigrate(&models.Pipeline{}, &models.Step{}, &models.Execution{})

	r := gin.Default()
	api.RegisterRoutes(r)
	return r
}

Primeiro vamos testar a criação de um pipeline. Devemos esperar desse request um retorno de sucesso.

Ler Mais

79/100 Dias de Golang - Mini Servidor de CI/CD – Parte 3 - Implementação da API com Gin

# Mini Servidor de CI/CD – Parte 3: Implementação da API com Gin

Na Parte 2, criamos o banco de dados e modelamos nossas entidades com GORM. Agora, vamos adicionar a camada de API que permitirá: Criar novos pipelines, listar pipelines existentes e executar um pipeline específico. Iremos utilizar o Gin. Teremos dois arquivos novos nessa etapa do projeto o internal/api/routes.go e o internal/api/handlers.go.

No arquivo routes.go, definimos as 3 rotas e quais os handlers de cada rota:

Ler Mais

78/100 Dias de Golang - Mini Servidor de CI/CD – Parte 2 - Modelagem e Banco de Dados com GORM

# Mini Servidor de CI/CD – Parte 2: Modelagem e Banco de Dados com GORM

Na Parte 1, iniciamos nosso projeto de servidor CI/CD com Go e o framework Gin, configurando a estrutura de pastas e subindo o servidor com uma rota de teste. Agora vamos persistir os dados dos pipelines e suas execuções com GORM e SQLite. Nosso servidor CI/CD precisa lidar com três entidades principais:

  1. Pipeline: representa uma definição de tarefas a serem executadas.
  2. Step: cada comando a ser executado dentro do pipeline.
  3. Execution: representa uma execução (histórico) de um pipeline.

Primeiro vamos instalar o GORM e o driver do sqlite:

Ler Mais

77/100 Dias de Golang - Mini Servidor de CI/CD – Parte 1 - Visão Geral do Projeto

# Mini Servidor de CI/CD – Parte 1: Visão Geral do Projeto

Vamos construir nosso mini servidor de CI/CD com Golang! Nesta “série” de quatro artigos, vamos desenvolver um mini servidor de CI/CD utilizando Golang. Nosso objetivo é criar um sistema simples, porém funcional, que permita: Cadastrar pipelines via API. Listar todos os pipelines existentes. Executar pipelines sob demanda.Persistir informações de execução em banco de dados. Validar a aplicação com testes.

Ler Mais

76/100 Dias de Golang - Hot Reload com Air

# Hot Reload com Air

Ficar cancelando o go run main.go no terminal ou recompilando manualmente a cada alteração é bem cansativo. Para resolver isso, podemos usar o Air: uma ferramenta de hot reload que detecta mudanças nos arquivos e recompila automaticamente sua aplicação.

Vamos criar um projeto e instalar a dependência:

go install github.com/air-verse/air@latest

E no nosso main.go criar um endpoint bem simples:

package main

import (
	"fmt"
	"net/http"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "Olá victorstein.dev")
	})
	fmt.Println("Olá victorstein.dev")
	http.ListenAndServe(":8080", nil)
}

Depois rodamos somente um comando:

Ler Mais

75/100 Dias de Golang - Docker e Golang

# Docker e Golang

Neste post, vamos criar uma API simples com Golang usando o framework Gin, e empacotá-la em uma imagem Docker enxuta e pronta para deploy.

package main

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()

	r.GET("/", func(c *gin.Context) {
		c.String(http.StatusOK, "Olá do servidor Go com Gin em Docker!")
	})

	r.Run(":8080")
}

Uma das grandes vantagens do Golang é que ele compila o código em um único executável estático. Isso permite criar imagens Docker extremamente leves, contendo apenas o binário da aplicação. Para aproveitar ao máximo essa característica, vamos utilizar um multi-stage build no Docker. Começaremos mostrando o segundo estágio, responsável apenas por rodar o executável final.. Veja como ela será simples, vamos usar a imagem alpine, definir um workdir, copiar nosso executável, e executar o arquivo compilado.

Ler Mais

74/100 Dias de Golang - Panic e Recover

# Panic e Recover

Para fechar a tríplice, vamos falar sobre panic e recover. O Panic é uma função que interrompe o fluxo normal de execução do programa e o recover é uma função que permite capturar um panic e retomar o controle do programa. Ela só funciona dentro de funções defer.

Veja esse exemplo do panic:

func dividir(a, b int) int {
    if b == 0 {
        panic("divisão por zero não é permitida")
    }
    return a / b
}

Se você rodar e executar essa função, o programa vai dar um erro e encerrar. Será que esse é o comportamento que queremos em uma API? Vamos ver como ficaria essa função tratando o erro com um recover:

Ler Mais

73/100 Dias de Golang - Panic, Defer e Recover

# Panic, Defer e Recover

Estava buscando temas e coisas ainda não abordadas. E vi que ainda não falei especificamente sobre Panic, Defer e Recover. Hoje vamos falar mais osbre o Defer.

# Defer

O defer é muito simples, ele agenda um execução para logo antes do return da atual função. Veja esse exemplo:

func deferExemplo() {
    fmt.Println("Início")
    defer fmt.Println("Fim")
    fmt.Println("Meio")
}

A saída será:

Ler Mais

72/100 Dias de Golang - Criando um linter básico com golang - Buscando ifs dentro de ifs

# Criando um linter básico com golang - Buscando ifs dentro de ifs

Pensei em criar um função que analisa o código em busca de ifs aninhados. Vamos usar a mesma base do projeto e só adicionar mais duas funções no arquivo de regras.

Vamos fazer o mesmo esquema com o ast.Inspect e avaliar node por node. Aqui vou fazer um switch no statement, para no caso de adicionar mais algumas verificações, mas poderia ser um if para validar se o statement é um if.

Ler Mais

71/100 Dias de Golang - Criando um linter básico com golang

# Criando um linter básico com golang

Um linter é uma ferramenta que analisa o código e encontra problemas de estilo, inconsistências, possíveis erros, … Ele funciona como um corretor gramatical e de estilo para o código, sem realmente executá-lo, faz isso através de uma análise estática. No Python temos o ruff, Pylint, Flake8, no javascript temos o eslint e no golang temo o golangci-lint. E de forma bem resumida eles funcionam da seguinte forma: o linter “lê” o código, gera uma árvore AST (árvore de sintaxe abstrata) e o linter lê essa árvore aplicando regras. No golang temos Oo pacote go/ast permite ler, analisar e manipular o código-fonte Go como uma árvore de sintaxe abstrata. Vamos criar o victorlinter todas as funções devem começar com o nome victor.

Ler Mais