GovHub Data Lakehouse
Data Lakehouse format-agnostic e infra-agnostic: a mesma camada de orquestração funciona independente de object storage, catálogo de metadados, engine de query e formato de tabela por baixo (Iceberg, Delta Lake, Hudi).
docs/REQUIREMENTS.md— visão, requisitos e arquiteturadocs/USER_STORIES.md— histórias de usuário e ordem de execução
Stack
- Core: Python, gerenciado com
uv - Infra como código: Terraform (módulos por ambiente:
local,aws, ...) - Versões de ferramentas:
mise(.mise.toml)
Subindo o ambiente local
mise trust
mise install
cp .env.example .env # ajuste se necessário — os defaults já batem com a infra local
cd infra/environments/local
terraform init
terraform apply
terraform apply só retorna quando todos os serviços respondem como
saudáveis (ver null_resource.wait_for_services em
infra/environments/local/main.tf) — não só quando os containers existem.
Evita testes/comandos rodando contra um serviço (ex: Trino) que ainda não
terminou de subir.
Sobe, via Docker:
| Serviço | Endpoint | Login |
|---|---|---|
| MinIO API (S3) | http://localhost:9003 | lakehouse / lakehouse-dev |
| MinIO Console | http://localhost:9002 | lakehouse / lakehouse-dev |
| Iceberg REST Catalog | http://localhost:8181 | — |
| Airflow (standalone) | http://localhost:8082 | admin / ver comando abaixo |
| Trino | http://localhost:8083 | — |
Senha do Airflow (gerada na primeira subida, persiste no volume):
docker exec govhub-lakehouse-airflow cat /opt/airflow/simple_auth_manager_passwords.json.generated
Bucket warehouse é criado automaticamente no MinIO. Catálogo Iceberg
persiste metadados em Postgres (porta 5434).
Para derrubar: terraform destroy dentro de infra/environments/local.
Configuração (.env)
.env.example documenta todas as variáveis GOVHUB_* (storage, catálogo,
extractors) com os defaults que já batem com a infra local, mais
GOVHUB_ENV (dev | homolog | prod — qual ambiente este checkout
está apontando agora; aparece no log de auditoria da CLI). Copie pra .env
(gitignorado) e ajuste — mise carrega automaticamente em todo comando
rodado via mise exec (.mise.toml), sem depender de nenhuma lib Python.
Rodando o core Python
uv sync
uv run pytest tests/
Testes contra backends reais (s3 em tests/storage/, iceberg_rest em
tests/catalog/ e tests/table/, DuckDB + Trino em tests/engines/)
precisam do ambiente local do Terraform no ar — caso contrário são
pulados automaticamente.
Storage backend
Backend escolhido via GOVHUB_STORAGE_BACKEND (local ou s3). Os demais
nomes são genéricos de propósito — os mesmos valerão para os próximos
backends (Azure, GCS):
| Variável | Uso |
|---|---|
GOVHUB_STORAGE_BACKEND |
local | s3 |
GOVHUB_STORAGE_LOCAL_ROOT |
raiz no filesystem (backend local) |
GOVHUB_STORAGE_CONTAINER |
bucket/container |
GOVHUB_STORAGE_ENDPOINT |
endpoint do serviço |
GOVHUB_STORAGE_ACCESS_KEY |
credencial de acesso |
GOVHUB_STORAGE_SECRET_KEY |
credencial secreta |
GOVHUB_STORAGE_REGION |
região (quando aplicável) |
Catalog backend
Backend escolhido via GOVHUB_CATALOG_BACKEND (iceberg_rest por
enquanto):
| Variável | Uso |
|---|---|
GOVHUB_CATALOG_BACKEND |
iceberg_rest |
GOVHUB_CATALOG_URI |
endpoint do catálogo REST |
GOVHUB_CATALOG_WAREHOUSE |
localização do warehouse (s3://...) |
GOVHUB_CATALOG_ENDPOINT |
endpoint do object storage (S3 FileIO) |
GOVHUB_CATALOG_ACCESS_KEY |
credencial de acesso |
GOVHUB_CATALOG_SECRET_KEY |
credencial secreta |
GOVHUB_CATALOG_REGION |
região (quando aplicável) |
Table format backend
Sem variáveis próprias — reaproveita a config do catálogo (GOVHUB_CATALOG_*
acima), já que a camada de formato sempre opera sobre uma conexão de
catálogo existente. Seleção do formato é por código (TableBackendFactory),
iceberg por enquanto.
Extractors e transformers
src/govhub_lakehouse/extractors/ (Strategy + Factory, mesmo padrão de
core/) — ApiExtractor, PostgresExtractor, S3Extractor, registrados
em ExtractorFactory. src/govhub_lakehouse/transformers/ (Template
Method) — IcebergTransformer cuida do passo específico de formato
(ajustar o schema solto do extractor para exatamente o que o Iceberg
espera) dentro de um algoritmo fixo (transform) compartilhado por
qualquer formato futuro.
DAGs (dags/)
Ingestão organizada por domínio de dados (estilo data mesh, mesma lógica
do govhub-cidades) — cada domínio tem sua própria pasta/DAG(s) sob
dags/<domínio>/, montada em /opt/airflow/dags. Exemplo real:
dags/ibge/estados_dag.py — domínio ibge, extract >> transform via
TaskFlow API, puxando a lista de estados da API pública do IBGE e
carregando em ibge.estados (Iceberg).
docker exec govhub-lakehouse-airflow airflow dags unpause ibge_estados
docker exec govhub-lakehouse-airflow airflow dags trigger ibge_estados
docker exec govhub-lakehouse-airflow airflow dags list-runs ibge_estados
A imagem do Airflow é buildada com o próprio pacote instalado
(infra/modules/orchestration/local/docker/airflow/Dockerfile), então
qualquer DAG pode importar govhub_lakehouse.extractors/.transformers/
.core.* normalmente.
Lint
uv run black --check src tests dags
uv run isort --check src tests dags
CLI (glh)
uv run glh init
uv run glh create-table --namespace ns --table people --column id:long:required --column name:string
uv run glh ingest --namespace ns --table people --file dados.parquet [--mode append|overwrite]
uv run glh list-tables --namespace ns
uv run glh describe-table --namespace ns --table people
Cada comando lê a config de GOVHUB_STORAGE_*/GOVHUB_CATALOG_* (acima) e
emite um log estruturado em JSON por operação em stderr — quem rodou
(usuário do SO), quando, quais argumentos, sucesso/erro e duração. O
resultado da operação vai pro stdout, também em JSON.
Build e deploy
Pra implantar o glh na infra de um órgão, sem precisar de Python/uv
instalado lá:
uv build # wheel + sdist em dist/
docker build -t govhub-lakehouse-cli . # imagem standalone do CLI
docker run --rm govhub-lakehouse-cli init # roda contra GOVHUB_STORAGE_*/GOVHUB_CATALOG_* passadas via -e
A imagem não inclui nossa infra local de dev — só o glh e suas
dependências. O órgão aponta as variáveis de ambiente pro storage/catálogo
deles.
Também publicamos duas imagens no GHCR a cada push na main (CD, ver
abaixo):
docker pull ghcr.io/bottinolucas/govhub-lakehouse-cli:latest
docker pull ghcr.io/bottinolucas/govhub-lakehouse-airflow:latest
A -airflow já vem com govhub_lakehouse instalado — é a mesma imagem
que infra/modules/orchestration/local builda localmente, só que pronta
pra puxar em vez de buildar.
CI/CD
.github/workflows/ci.yml roda em todo push/PR na main:
-
lint:
black+isort(src,tests,dags) -
terraform:
fmt -check+validate -
test: sobe a infra local via Terraform (só retorna com tudo saudável — ver
null_resource.wait_for_services), rodapytest, derruba a infra no final, mesmo se os testes falharem -
build:
uv build+ build das duas imagens Docker (CLI e Airflow) -
publish (CD — só em push na
main, nunca em PR, só depois que os outros quatro jobs passarem): publica as duas imagens no GHCR (ghcr.io/bottinolucas/govhub-lakehouse-{cli,airflow}), usando oGITHUB_TOKENnativo — nenhum secret extra a configurar. -
publish-pypi (CD — só em tag
v*, ex:v0.1.0, nunca em push simples): publica o wheel/sdist no PyPI via Trusted Publishing (OIDC — sem token pra guardar). Precisa de um passo manual único, feito uma vez no site do PyPI, antes do primeiro release:- Acesse https://pypi.org/manage/account/publishing/ (logado na conta que vai ser dona do pacote)
- Em "Add a new pending publisher", preencha:
- PyPI project name:
govhub-lakehouse(ou o nome que preferir — precisa bater com onameempyproject.toml) - Owner:
bottinolucas - Repository name:
govhub-data-lakehouse - Workflow name:
ci.yml - Environment name:
pypi
- PyPI project name:
- Pra liberar:
git tag v0.1.0 && git push origin v0.1.0(a versão da tag deve bater comversionempyproject.toml— PyPI rejeita reenviar uma versão já publicada).
Metadata
Release files for govhub-lakehouse 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| govhub_lakehouse-0.1.0.tar.gz | 18.3 kB | With provenance | Details for govhub_lakehouse-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| govhub_lakehouse-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for govhub_lakehouse-0.1.0-py3-none-any.whl |
Total release size: 56.8 kB
Release files / govhub_lakehouse-0.1.0.tar.gz
| Download URL | govhub_lakehouse-0.1.0.tar.gz |
|---|---|
| Size | 18.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f69242caecab50b576451f066da292fcee587ad5708bc74fbc75e0d361c1159e
|
|
BLAKE2b-256 checksum How to use checksums |
0ebfe7e899a6ce32c5de3a9acfe3fc63bf04dbc62789313dfda15b5b724a9afd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.
Transparency logRelease files / govhub_lakehouse-0.1.0-py3-none-any.whl
| Download URL | govhub_lakehouse-0.1.0-py3-none-any.whl |
|---|---|
| Size | 38.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e494df6c48aac04bb031ff3e632d1469cda194cd55a39b6e55f1c93d844abb45
|
|
BLAKE2b-256 checksum How to use checksums |
a3cd0fe930ce26c3552bebb4817ca4327a5eece176b2c2b7a346b6a0a2f4cc16
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.
Transparency logSecurity for govhub-lakehouse 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for govhub_lakehouse-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.