Essa é uma visualização multi-página imprimível desta seção. Aperte aqui para imprimir a página.
Guia de desenvolvimento
1 - Configuração de Ambiente
Configuração de Ambiente e Variáveis .env
Este guia explica como preparar o ambiente de desenvolvimento e configurar os arquivos .env
no backend e no frontend.
1. Visão Geral do Projeto
- Backend: Node.js, Express, Sequelize, testes com Jest e Supertest.
- Frontend: Next.js, TailwindCSS e componentes da biblioteca Shadcn UI.
- Banco de Dados: PostgreSQL (Sequelize).
- Armazenamento de arquivos: buckets em S3 compatível.
- Envio de e-mails: serviço configurado via variáveis
.env
.
2. Pré-requisitos
Antes de iniciar, certifique-se de que as seguintes ferramentas estão instaladas:
Node.js (versão LTS, 18 ou superior) Download Node.js Verifique a instalação:
node -v
pnpm (gerenciador de pacotes) Instalação:
npm install -g pnpm
Verifique a instalação:
pnpm -v
PostgreSQL (instalação local ou acesso a servidor remoto) Download PostgreSQL Verifique a instalação:
psql --version
Hugo (Necessário para rodar a documentação) Download Hugo Verifique a instalação:
hugo version
Outras ferramentas úteis:
- Docker (opcional, para rodar banco ou serviços auxiliares em containers)
- pgAdmin ou DBeaver (clientes gráficos para PostgreSQL)
3. Arquivos .env
Cada parte do sistema possui um arquivo de variáveis de ambiente de exemplo.
Esses arquivos não devem ser versionados com dados reais, apenas mantidos como .env.example
para referência.
Backend (.env.example
)
PORT=
JWT_KEY=
DB_SGBD=
DB_USER=
DB_PASSWORD=
DB_HOST=
DB_PORT=
DB_NAME=
S3_ACCESS_KEY_ID=
S3_SECRET_ACCESS_KEY=
S3_ENDPOINT=
S3_DOCS_BUCKET=
S3_PS_BUCKET=
S3_IMAGE_BUCKET=
S3_CONTRACT_AMMENDMENTS_BUCKET=
MAIL_HOST=
MAIL_PORT=
MAIL_ADDRESS=
ADMIN_MANAGER_MAIL=
Frontend (.env.development.example
)
NEXT_PUBLIC_API_BASE_URL="http://localhost:5000/api"
4. Setup do Ambiente
4.1 Backend
Instale dependências:
pnpm install
Copie o arquivo
.env.example
para.env
e preencha os valores locais:cp .env.example .env
Inicie o servidor em modo desenvolvimento:
pnpm start
4.2 Frontend
Instale dependências:
pnpm install
Copie o arquivo
.env.development.example
para.env.development
e preecha os valores locais:cp .env.development.example .env.development
Inicie o servidor de desenvolvimento do Next.js:
pnpm dev
O frontend será iniciado normalmente em http://localhost:3000
(ou na porta configurada).
4.3 Banco de Dados
O banco usado é PostgreSQL. Para acessar manualmente o ambiente de desenvolvimento:
psql -h <DB_HOST> -U <DB_USER> -d <DB_NAME>
Substitua <DB_HOST>
, <DB_USER>
e <DB_NAME>
pelos valores definidos no .env
.
4.4 Documentação
Para rodar a documentação localmente, basta acessar o diretorio específico e executar o comando:
hugo server
5. Boas Práticas
- Sempre mantenha arquivos
.env.example
atualizados com todas as variáveis necessárias. - Nunca versione o arquivo
.env
com dados reais. - Utilize variáveis distintas para desenvolvimento, teste e produção.
- Em produção, as variáveis devem ser configuradas diretamente no ambiente (por exemplo, via secrets do GitLab CI/CD). Apenas maintainers do projeto têm acesso a essas configurações.
- Sempre que uma variável for criada ou alterada, comunique a equipe Root, que é responsável por atualizar os valores nas variáveis de ambiente do Kubernetes.
2 - Configuração de Servidor de E-mails
Visão Geral
O envio de e-mails no Ademir é feito utilizando o msmtp, uma ferramenta leve que funciona como cliente SMTP e pode ser usada como substituto do sendmail
.
A configuração é feita por meio do arquivo .msmtprc
, que define os parâmetros de autenticação e envio.
Exemplo de Arquivo de Configuração
A seguir, um exemplo funcional de configuração (/etc/msmtprc
ou ~/.msmtprc
):
# Configuração padrão do msmtp
# Conta padrão utilizada pelo sistema
account default
# Servidor SMTP (smarthost)
host smtp.c3sl.ufpr.br
port 25
from root@ademir.c3sl.ufpr.br
domain ademir.c3sl.ufpr.br
user ademir
# Log via syslog com a facility LOG_MAIL
syslog LOG_MAIL
Detalhes dos Parâmetros
- account default → define a conta padrão para envio.
- host → endereço do servidor SMTP.
- port → porta utilizada (no exemplo,
25
). - from → endereço de e-mail que será usado como remetente.
- domain → domínio associado ao envio.
- user → usuário da conta SMTP.
- syslog LOG_MAIL → ativa logs no syslog com facility
LOG_MAIL
, permitindo auditoria.
Uso no Sistema
Com essa configuração, o msmtp
pode ser utilizado como se fosse o sendmail
, por exemplo:
echo "Teste de envio" | msmtp -a default destinatario@exemplo.com
No Ademir, essa configuração é usada pelo backend (via Nodemailer) para envio de e-mails transacionais e notificações.
Boas Práticas
Proteger o arquivo
.msmtprc
com permissões restritas:chmod 600 ~/.msmtprc
Em ambientes de produção, considerar uso de autenticação segura (porta 587 + STARTTLS).
Monitorar os logs via syslog para depuração de problemas de envio.
3 - Fluxo do Git
Guia de Fluxo de Trabalho
1. Selecionar uma Issue
Escolha uma issue entre as que estão atribuídas a você. Verifique as tarefas e determine qual delas será sua responsabilidade.
2. Criar uma Branch a partir da develop
Certifique-se de que a branch develop
está atualizada antes de criar sua nova branch.
- Vá para a branch
develop
:
git checkout develop
- Atualize a branch
develop
com as últimas alterações do repositório remoto:
git pull origin develop
- Criar e mudar para uma nova branch seguindo o padrão da issue:
issue-<número_da_issue>/<palavras-chave>
📌 Por que usar esse padrão?
- Cada issue no GitLab recebe automaticamente um número único.
- Esse número deve estar presente no nome da branch para facilitar a rastreabilidade.
- As palavras-chave, separadas exclusivamente por hífens, descrevem de forma objetiva o que está sendo feito.
Exemplo:
issue-256/fix-login-form
Criação da branch:
git checkout -B issue-<número_da_issue>/<palavras-chave>
3. Desenvolver a Feature na Branch
Faça as alterações necessárias para resolver a issue. Lembre-se de fazer commits pequenos e descritivos.
- Adicione as alterações ao índice:
git add .
💡 Dica:
O comando git add -A
é mais confiável que o git add .
, pois o segundo refere-se somente à pasta atual e suas subpastas.
- Faça o commit das alterações:
git commit -m "breve descrição"
4. Rebase da develop
para Sua Branch
Antes de finalizar o trabalho, faça um rebase para garantir que sua branch esteja atualizada com as últimas mudanças da develop
e para transformar todos seus commits em um só.
- Vá para a branch
develop
:
git checkout develop
- Atualize a branch
develop
:
git pull origin develop
- Volte para sua branch de desenvolvimento:
git checkout nome-da-branch
💡 Dica:
O comando git checkout -
volta para a última branch acessada.
- Rebase da branch em relação à
develop
:
git rebase -i develop
Isso abrirá uma tela no editor com a lista de commits da sua branch, todos precedidos por "pick"
.
✏️ Como editar os commits?
- Mantenha
pick
apenas no primeiro commit. - Altere todos os demais para
f
(de fixup), consolidando-os no primeiro. - Verifique se a mensagem do primeiro commit está correta, seguindo o formato:
Issue #<número_da_issue>: <Palavra de Poder> <descrição do que foi feito, em inglês>
- Se estiver correto: basta salvar e fechar o editor.
- Se estiver errado: troque
pick
parar
(reword), salve e feche o editor. Um novo editor irá abrir somente com o nome do commit a ser alterado.
🔹 Palavras de Poder
Use uma das palavras abaixo para indicar a natureza da mudança:
- Add
- Change
- Deprecate
- Remove
- Fix
- Security
Essas palavras seguem o padrão Keep a Changelog.
📌 Exemplo de commit correto
Issue #256: Fix login form was not working when Enter was pressed
Conflitos durante o rebase
Caso ocorram conflitos, resolva-os e depois:
git add -A
git rebase --continue
💡 Dica: O VSCode possui uma interface que ajuda muito nessa hora!
5. Push e Merge Request (MR)
Depois de finalizar o trabalho, envie sua branch para o repositório remoto e abra um Merge Request (MR) para revisão de código.
- Envie a branch para o repositório remoto:
git push origin nome-da-branch -f
💡 Dica:
A flag -f
(force) deve ser usada porque após o rebase o histórico foi reescrito.
Verifique se sua branch está com 0 commits atrás da
develop
e 1 commit à frente dadevelop
. Isso é indicado no GitLab pela notação0|1
ao lado do nome da branch.Abra o Merge Request (MR) no GitLab para revisão de código. Inclua uma descrição clara (o quê e por quê) e cite impactos (ex.: variáveis
.env
, migrações).
Conclusão
Esse fluxo de trabalho:
- Mantém o histórico do Git limpo (1 commit por issue).
- Organiza as alterações de forma eficiente.
- Facilita a colaboração em equipe, revisões e criação de releases.
Este fluxo é obrigatório dentro do C3SL e não deve ser alterado sem um motivo justificado de organização de código e fluxo de trabalho.
Guia rápido para criar uma Tag de Release
Para gerar uma nova Release e disparar o CI, basta criar e enviar a tag:
git tag vX.X.X
git push origin vX.X.X
Substitua vX.X.X
pela versão desejada (ex.: v1.0.0
). Isso acionará os jobs de release e criação de imagens no pipeline.
4 - Gerando o seed.sql para inicialização do banco no Docker
Objetivo: gerar um arquivo
seed.sql
que inicializa o banco com esquema, usuário de aplicação e permissões de aplicação. Observação: os itens “usuário” e “permissões” abaixo referem-se às tabelas da aplicação (ex.:user_system
,permissions
), não a roles do PostgreSQL.
Pré-requisitos
- Docker e Docker Compose instalados.
- Acesso ao banco remoto
postgres.c3sl.ufpr.br
com o usuárioademir
. - Arquitetura do projeto contendo a pasta
database/
.
0) Backup do seed atual (opcional, recomendado)
Renomeie o seed atual para manter como backup.
mv database/seed.sql database/seed_$(date +%Y%m%d_%H%M%S).sql
1) Exportar apenas o esquema do banco remoto
Na raiz do projeto, execute:
pg_dump -h postgres.c3sl.ufpr.br -U ademir -d ademir --schema-only > database/seed.sql
Quando solicitado, insira a senha do banco.
Dica: para evitar prompt interativo, você pode usar
PGPASSWORD=suasenha pg_dump ...
.
2) Subir o Postgres local via Docker Compose
docker compose up postgres -d
3) Acessar o banco dentro do container
docker exec -it ademir-db psql -U ademir -d ademir
4) Criar permissões na tabela permissions
INSERT INTO permissions (name, "createdAt", "updatedAt")
SELECT 'admin', NOW(), NOW()
WHERE NOT EXISTS (
SELECT 1 FROM permissions WHERE name = 'admin'
);
INSERT INTO permissions (name, "createdAt", "updatedAt")
SELECT 'common', NOW(), NOW()
WHERE NOT EXISTS (
SELECT 1 FROM permissions WHERE name = 'common'
);
INSERT INTO permissions (name, "createdAt", "updatedAt")
SELECT 'manager', NOW(), NOW()
WHERE NOT EXISTS (
SELECT 1 FROM permissions WHERE name = 'manager'
);
5) Criar usuário inicial admin
INSERT INTO user_system (
name,
email,
password,
is_active,
"isEmailVerified",
register_date,
verification_date,
last_login
) VALUES (
'admin',
'admin@mail.com',
'mudar123*', -- ⚠️ idealmente armazenar com hash
TRUE,
TRUE,
NOW(),
NOW(),
NOW()
);
6) Gerar o novo seed.sql
com dados
Ainda na raiz do projeto, execute:
docker exec -it ademir-db pg_dump -U ademir -d ademir > database/seed.sql
5 - Integração Contínua (CI/CD)
Integração Contínua (CI/CD)
Este guia explica o pipeline do GitLab: lint → test → build → release → image_create → create-pages. Também lista as variáveis necessárias e como acionar cada etapa.
1) Estrutura geral do pipeline
cache:
paths:
- node_modules
stages:
- lint
- test
- build
- release
- image_create
- create-pages
lint-job:
image: $CI_REGISTRY/ademir/node-custom:latest
stage: lint
script:
- ln -s /ci-modules/backend_node_modules backend/node_modules
- cd backend
- pnpm lint
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
test-job:
image: $CI_REGISTRY/ademir/node-custom:latest
stage: test
script:
- ln -s /ci-modules/backend_node_modules backend/node_modules
- cd backend
- pnpm exec tsc && pnpm exec jest --ci --forceExit --detectOpenHandles --runInBand --silent --verbose=false
variables:
NODE_ENV: testing
DB_SGBD: ${DB_SGBD}
DB_USER: ${DB_USER}
DB_PASSWORD: ${DB_PASSWORD}
DB_HOST: ${DB_HOST}
DB_PORT: ${DB_PORT}
DB_NAME: ${DB_NAME}
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
build-job:
image: $CI_REGISTRY/ademir/node-custom:latest
stage: build
script:
- ln -s /ci-modules/frontend_node_modules frontend/node_modules
- cd frontend
- pnpm run build
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
create_release:
stage: release
image: $CI_REGISTRY/ademir/release-cli
script:
- |
LAST_TAG=$(git tag --sort=-creatordate | sed -n 2p)
if [ -z "$LAST_TAG" ]; then
git log --pretty=format:"%s (%an)" | grep -v "^Merge branch" | sed 's/^/- /' > release_notes.md
else
git log "${LAST_TAG}"..HEAD --pretty=format:"%s (%an)" | grep -v "^Merge branch" | sed 's/^/- /' > release_notes.md
fi
echo "Versão: $CI_COMMIT_TAG" > full_release.md
echo "" >> full_release.md
echo "Mudanças:" >> full_release.md
cat release_notes.md >> full_release.md
release:
tag_name: $CI_COMMIT_TAG
name: "Release $CI_COMMIT_TAG"
description: full_release.md
rules:
- if: '$CI_COMMIT_TAG'
image_create:
stage: image_create
image:
name: $CI_REGISTRY/ademir/buildah
script:
- buildah login -u "$HARBOR_LOGIN" -p "$HARBOR_PASSWORD" "$CI_REGISTRY"
- buildah build --layers --build-arg NEXT_PUBLIC_API_BASE_URL="$NEXT_PUBLIC_API_BASE_URL" --file frontend/Containerfile --tag $CI_REGISTRY/ademir/frontend:$CI_COMMIT_TAG --cache-from=$CI_REGISTRY/ademir/frontend --cache-to=$CI_REGISTRY/ademir/frontend frontend
- buildah push harbor.c3sl.ufpr.br/ademir/frontend:$CI_COMMIT_TAG
- buildah build --layers --file backend/Containerfile --tag harbor.c3sl.ufpr.br/ademir/backend:$CI_COMMIT_TAG --cache-from=$CI_REGISTRY/ademir/backend --cache-to=$CI_REGISTRY/ademir/backend backend
- buildah push harbor.c3sl.ufpr.br/ademir/backend:$CI_COMMIT_TAG
rules:
- if: '$CI_COMMIT_TAG'
# deploy (k8s) — desativado
#deploy:
# stage: deploy
# image: bitnami/kubectl:latest
# script:
# - kubectl --kubeconfig $KUBECONFIG rollout restart deploy ademir -n ademir
# rules:
# - if: '$CI_COMMIT_TAG'
create-pages:
image: hugomods/hugo:ci
variables:
GIT_SUBMODULE_STRATEGY: recursive
before_script:
- cd docs
- npm i -D postcss postcss-cli autoprefixer
script:
- hugo --minify -D -d public
- mv public ..
pages: true
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
changes:
- docs/**/*
environment: production
Observação: os blocos estão sem linguagem para manter compatibilidade com a diretriz de apenas blocos de código Markdown.
2) Quando cada estágio roda
- lint, test, build → executam em Merge Requests (
rules: if: $CI_PIPELINE_SOURCE == "merge_request_event"
). - release e image_create → executam somente em tag (
rules: if: $CI_COMMIT_TAG
). - create-pages (Hugo) → executa na branch padrão (ex.:
develop
) quando houver mudanças emdocs/
.
Disparo prático
- Abrir MR → roda lint, test, build.
- Criar tag (ex.:
v1.2.3
) → roda create_release e image_create (gera release e imagens e faz push no registry). - Commits em
docs/
na branch padrão → roda create-pages e publica a documentação.
3) Variáveis de ambiente (CI/CD) necessárias
Crie/atualize em Settings → CI/CD → Variables no GitLab:
Backend / Testes
DB_SGBD
DB_USER
DB_PASSWORD
DB_HOST
DB_PORT
DB_NAME
Release / Imagens
HARBOR_LOGIN
— login no registryHARBOR_PASSWORD
— senha/token do registryNEXT_PUBLIC_API_BASE_URL
— base URL injetada no build do frontend- (opcional)
CI_REGISTRY
,CI_REGISTRY_USER
,CI_REGISTRY_PASSWORD
se o runner exigir login explícito
Outras
CI_DEFAULT_BRANCH
(já fornecida pelo GitLab)KUBECONFIG
(se reativar o job de deploy)
Boas práticas: marque variáveis sensíveis como masked e protected; ligue Protect para usar apenas em branches/tags protegidas.
4) Detalhes de cada job
lint-job
- Usa imagem Node custom.
- Cria symlink para
backend/node_modules
apontando para/ci-modules/backend_node_modules
(cache aquecido da imagem). - Roda
pnpm lint
no diretóriobackend
.
test-job
- Mesmo setup de node_modules do
lint-job
. - Compila TypeScript (
pnpm exec tsc
) e executa testes com Jest/Supertest. - Injeta variáveis de banco para testes.
build-job
- Prepara
frontend/node_modules
via symlink. - Executa
pnpm run build
emfrontend
(Next.js + Tailwind + shadcn).
create_release
- Gera release notes a partir do
git log
(desde a última tag) e cria um Release associado à tag atual ($CI_COMMIT_TAG
).
image_create
- Autentica no registry (
buildah login
). - Frontend: build da imagem passando
NEXT_PUBLIC_API_BASE_URL
por--build-arg
; faz push paraharbor.c3sl.ufpr.br/ademir/frontend:$CI_COMMIT_TAG
. - Backend: build e push da imagem
harbor.c3sl.ufpr.br/ademir/backend:$CI_COMMIT_TAG
. - Usa camadas em cache (
--layers
,--cache-from/--cache-to
).
create-pages
- Usa imagem do Hugo.
- Instala
postcss
,postcss-cli
eautoprefixer
para o tema. - Gera site (
hugo --minify -D
) e publica artefatos para Pages.
5) Fluxos típicos
A) Verificação de MR
- Abrir MR → pipeline executa lint, test, build.
- Corrigir problemas (se houver) → push para a mesma branch reexecuta as etapas.
B) Criar release e imagens
- Marcar uma tag (ex.:
v1.2.3
). - Pipeline executa
create_release
eimage_create
. - Conferir release no GitLab e imagens no registry Harbor.
C) Publicar documentação
- Subir commits na branch padrão alterando
docs/
. - Pipeline executa
create-pages
e publica o site (GitLab Pages).
6) Troubleshooting
- lint/test falhando: rode localmente
pnpm lint
epnpm exec jest
no diretório correspondente e verifique versões do Node. - Falha no build do frontend: cheque dependências (
pnpm install
) e teste pnpm build localmente. - Erro no
image_create
: valideHARBOR_LOGIN
/HARBOR_PASSWORD
e permissão de push no registry. Confirme o nome das imagens e tags. create-pages
não dispara: confirme a branch padrão e se houve mudanças dentro dedocs/
.- Variáveis ausentes: adicione em CI/CD Variables (acessível apenas pra mantainers) e proteja-as quando necessário.
7) Boas práticas
- Mantenha o pipeline rápido (cache eficiente, jobs paralelos quando possível).
- Use tags semânticas (ex.:
vX.Y.Z
) para releases. - Centralize secrets apenas no CI/CD; não versionar
.env
reais.