-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathMakefile
More file actions
232 lines (201 loc) · 10.2 KB
/
Copy pathMakefile
File metadata and controls
232 lines (201 loc) · 10.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
# Alvos do wrapper-api. `make help` lista todos.
#
# Regra que economiza tempo: a lib nativa NÃO se compila no host. O build com
# cgo real acontece no Docker multi-stage (etapa 7 do plano); aqui há um alvo
# build-cgo só para VALIDAR o binding contra .so já compiladas.
SHELL := /bin/bash
# ACBR_REV é a FONTE ÚNICA da revisão do ACBr: o script de download monta a tag
# do release a partir dela, e o snapshot de chaves do lockstep é regenerado em
# lockstep com ela. Ao bumpar, republique as libs e regenere os snapshots.
ACBR_REV ?= 48100
# O FortesReport CE entra nos .so junto com o ACBr (ele rasteriza DACTE/DAMDFE/
# DANFSE). Seguia o master, o que fazia METADE do binário flutuar enquanto o
# ACBr era pinado com cuidado: um build de 2026-08 pegou um FortesReport de
# 2026-08-06 onde o anterior tinha usado o de 2025-09-22, quase um ano antes.
ACBR_FRCE_REF ?= 9c29ee7152a6293d3920ff44a2bf3cd384d7b081
# Release que CARREGA os binários da ACBrLib. É uma tag v*, não um release
# próprio: a aba de Releases passa a ter só versões deste serviço. O arquivo
# revisao.txt vai junto dos .so e precisa bater com ACBR_REV, senão o download
# recusa: sem o nome da revisão na tag, nada mais amarraria as duas coisas.
ACBR_LIBS_RELEASE ?= v1.3.0
OUT := out
PKGS := ./...
ACBRLIBS ?= ./acbr-libs
ACBR_BASE_IMAGE ?= wrapper-api/acbrlib-base
ACBR_SRC ?= ./acbr-source
APP_IMAGE ?= wrapper-api:dev
LDFLAGS := -X github.com/4devsmart/wrapper-api/internal/platform/versao.Commit=$(shell git rev-parse HEAD 2>/dev/null) \
-X github.com/4devsmart/wrapper-api/internal/platform/versao.Build=$(shell date -u +%Y-%m-%dT%H:%M:%SZ)
.DEFAULT_GOAL := help
## build: compila api e fiscal-worker sem cgo (binding stub)
build:
CGO_ENABLED=0 go build -trimpath -ldflags "$(LDFLAGS)" -o $(OUT)/api ./cmd/api
CGO_ENABLED=0 go build -trimpath -ldflags "$(LDFLAGS)" -o $(OUT)/fiscal-worker ./cmd/fiscal-worker
## build-cgo: compila o worker com a ACBrLib real (exige as .so em ACBRLIBS)
build-cgo:
@test -f "$(ACBRLIBS)/libacbrcte64.so" || { \
echo "faltam as .so em $(ACBRLIBS): rode 'make acbr-libs-baixar'"; exit 1; }
CGO_ENABLED=1 \
CGO_LDFLAGS="-L$(abspath $(ACBRLIBS)) -Wl,-rpath,$(abspath $(ACBRLIBS))" \
go build -trimpath -tags acbrlib -ldflags "$(LDFLAGS)" -o $(OUT)/fiscal-worker-cgo ./cmd/fiscal-worker
## run: sobe a api local (sem worker: /readyz responde 503, é o esperado)
run:
CGO_ENABLED=0 go run ./cmd/api
## test: testes de unidade
test:
CGO_ENABLED=0 go test $(PKGS)
## test-integracao-nfse: raiz do XML por provedor contra uma API com worker
# Exige WRAPPER_API_URL (e WRAPPER_API_TOKEN se a API tiver token). Um
# município por (provedor, versão, API própria), cobrando que o XML gerado seja
# do layout que a tabela informa.
test-integracao-nfse:
@test -n "$(WRAPPER_API_URL)" || { echo "defina WRAPPER_API_URL"; exit 1; }
CGO_ENABLED=0 go test -tags integracao -run TestRaizDoXMLPorProvedor -count=1 -v ./internal/nfse
## test-cgo: type-check e link do binding cgo contra as .so (não executa a lib)
test-cgo:
@test -f "$(ACBRLIBS)/libacbrcte64.so" || { \
echo "faltam as .so em $(ACBRLIBS): rode 'make acbr-libs-baixar'"; exit 1; }
CGO_ENABLED=1 \
CGO_LDFLAGS="-L$(abspath $(ACBRLIBS)) -Wl,-rpath,$(abspath $(ACBRLIBS))" \
go vet -tags acbrlib $(PKGS)
## enums-conferir: compara os enums declarados com os schemas XSD oficiais
enums-conferir:
@python3 scripts/conferir-enums.py
## openapi: regenera os schemas da spec a partir dos modelos Go
openapi:
CGO_ENABLED=0 go run ./cmd/gerar-openapi
## openapi-valida: confere que a spec é YAML válido e está descrita
openapi-valida:
@python3 scripts/validar-openapi.py
## openapi-check: falha se a spec estiver desatualizada em relação aos modelos
openapi-check: openapi-valida
@cp api/openapi.yaml /tmp/openapi.antes.yaml
@CGO_ENABLED=0 go run ./cmd/gerar-openapi >/dev/null
@if ! diff -q /tmp/openapi.antes.yaml api/openapi.yaml >/dev/null; then \
echo "api/openapi.yaml está desatualizada: rode 'make openapi' e commite."; \
diff -u /tmp/openapi.antes.yaml api/openapi.yaml | head -40; \
cp /tmp/openapi.antes.yaml api/openapi.yaml; exit 1; \
fi
@echo "openapi.yaml em dia com os modelos"
## yaml-valida: confere que todo YAML rastreado parseia (workflows, compose, spec)
yaml-valida:
@python3 scripts/validar-yaml.py
## vet: go vet (build padrão)
vet:
CGO_ENABLED=0 go vet $(PKGS)
## fmt: gofmt em tudo
fmt:
gofmt -w .
## fmt-check: falha se algo estiver fora do gofmt (usado no CI)
fmt-check:
@saida=$$(gofmt -l .); \
if [ -n "$$saida" ]; then echo "fora do gofmt:"; echo "$$saida"; exit 1; fi
## tidy: go mod tidy
tidy:
go mod tidy
## acbr-fonte: baixa/atualiza o fonte do ACBr e do FortesReport em acbr-source/
acbr-fonte:
mkdir -p $(ACBR_SRC)
docker run --rm \
-v "$(abspath $(ACBR_SRC)):/work" \
-v "$(abspath scripts/acbr-fonte.sh):/acbr-fonte.sh:ro" \
-e ACBR_REV=$(ACBR_REV) -e FRCE_REF=$(ACBR_FRCE_REF) \
-e LANG=C.UTF-8 -e LC_ALL=C.UTF-8 \
debian:bookworm-slim sh -c \
'apt-get update -qq && apt-get install -y -qq --no-install-recommends subversion git ca-certificates >/dev/null && sh /acbr-fonte.sh'
## acbr-compilar: compila as .so a partir de acbr-source/ (offline, LENTO)
acbr-compilar:
@test -d $(ACBR_SRC)/acbr && test -d $(ACBR_SRC)/frce || { \
echo "falta o fonte em $(ACBR_SRC): rode 'make acbr-fonte'"; exit 1; }
docker build -f docker/acbrlib.Dockerfile --build-arg ACBR_REV=$(ACBR_REV) \
--build-context patches=docker/acbr-patches \
-t $(ACBR_BASE_IMAGE):dev \
-t $(ACBR_BASE_IMAGE):r$(ACBR_REV) $(ACBR_SRC)
## acbr-extrair: extrai as .so e os schemas da imagem compilada para acbr-libs/
# Extrai da tag :r$(ACBR_REV), NÃO de :dev. A :dev é a última coisa compilada,
# que não é necessariamente a revisão pinada: compilar uma e extrair outra
# passava sem aviso e punha .so de revisão errada dentro da imagem.
acbr-extrair:
@docker image inspect $(ACBR_BASE_IMAGE):r$(ACBR_REV) >/dev/null 2>&1 || { \
echo "imagem ausente para r$(ACBR_REV): rode 'make acbr-compilar'"; exit 1; }
mkdir -p $(ACBRLIBS)
@cid=$$(docker create $(ACBR_BASE_IMAGE):r$(ACBR_REV)); \
rm -rf $(ACBRLIBS)/_art && mkdir -p $(ACBRLIBS)/_art; \
docker cp $$cid:/artifacts/. $(ACBRLIBS)/_art/; \
docker rm $$cid >/dev/null; \
cp $(ACBRLIBS)/_art/*.so $(ACBRLIBS)/; \
tar -C $(ACBRLIBS)/_art -czf $(ACBRLIBS)/schemas.tar.gz schemas schemas-cte schemas-mdfe; \
rm -rf $(ACBRLIBS)/_art
@# Reger o SHA256SUMS aqui. Antes a extração trocava as .so e deixava o
@# arquivo da revisão anterior, então o diretório ficava se contradizendo:
@# "sha256sum -c" acusava as seis, e acbr-libs-conferir, que só olha tamanho,
@# dizia OK do mesmo jeito.
@cd $(ACBRLIBS) && sha256sum libacbrnfse64.so libacbrcte64.so libacbrmdfe64.so \
libacbrnfe64.so libacbrboleto64.so schemas.tar.gz > SHA256SUMS
@$(MAKE) --no-print-directory acbr-libs-conferir
## acbr-tabelas: regenera municipios_provedor.tsv a partir do fonte do ACBr
# Anda em lockstep com ACBR_REV: a tabela de provedor por município é a mesma
# que está compilada dentro da .so. Recusa emitir se aparecer provedor sem
# família classificada, em vez de gravar e deixar o teste pegar depois.
acbr-tabelas:
@test -d $(ACBR_SRC)/acbr || { \
echo "falta o fonte em $(ACBR_SRC): rode 'make acbr-fonte'"; exit 1; }
@python3 scripts/gerar-tabelas-nfse.py
## acbr-tabelas-conferir: falha se municipios_provedor.tsv divergir do fonte pinado
acbr-tabelas-conferir:
@python3 scripts/gerar-tabelas-nfse.py --conferir
## acbr-chaves: regenera os snapshots de chaves de INI que a lib aceita
# Gerado do fonte Pascal pinado. O TSV era editado à mão e tinha três erros:
# chave de fallback ausente (segundo argumento de ReadString aninhado), capM3
# gravado como capM porque o dígito final era tratado como índice, e onze chaves
# de [prop] gravadas em [veic].
acbr-chaves:
@test -d $(ACBR_SRC)/acbr || { \
echo "falta o fonte em $(ACBR_SRC): rode 'make acbr-fonte'"; exit 1; }
@python3 scripts/gerar-chaves-lerini.py
## acbr-chaves-conferir: falha se os snapshots divergirem do fonte pinado
acbr-chaves-conferir:
@python3 scripts/gerar-chaves-lerini.py --conferir
## acbr-libs-baixar: baixa as libs nativas dos anexos de release (cache local)
acbr-libs-baixar:
@ACBR_REV=$(ACBR_REV) ACBR_LIBS_DIR=$(ACBRLIBS) \
ACBR_LIBS_RELEASE=$(ACBR_LIBS_RELEASE) ./scripts/baixar-acbr-libs.sh
## acbr-libs-publicar: publica o cache local como release (uma vez por revisão)
acbr-libs-publicar:
@ACBR_REV=$(ACBR_REV) ACBR_LIBS_DIR=$(ACBRLIBS) \
ACBR_LIBS_RELEASE=$(ACBR_LIBS_RELEASE) ./scripts/publicar-acbr-libs.sh
## acbr-libs-conferir: valida o cache local antes do build
acbr-libs-conferir:
@falta=0; for f in libacbrnfse64.so libacbrcte64.so libacbrmdfe64.so \
libacbrnfe64.so libacbrboleto64.so schemas.tar.gz; do \
if [ ! -s "$(ACBRLIBS)/$$f" ]; then echo "faltando: $(ACBRLIBS)/$$f"; falta=1; \
elif [ "$$(stat -c%s "$(ACBRLIBS)/$$f")" -lt 1000000 ]; then \
echo "incompleto: $(ACBRLIBS)/$$f"; falta=1; fi; \
done; \
if [ "$$falta" = 1 ]; then echo; echo "Rode 'make acbr-libs-baixar'."; exit 1; fi
@echo "acbr-libs OK"
## imagem-libs-conferir: confere que as .so de IMAGEM são as do SHA256SUMS em acbr-libs/
# Rode depois do docker-build, ou contra uma imagem publicada:
# make imagem-libs-conferir IMAGEM=ghcr.io/4devsmart/wrapper-api/api:v1.3.1
imagem-libs-conferir:
@scripts/conferir-libs-imagem.sh "$(or $(IMAGEM),$(APP_IMAGE))" $(ACBRLIBS)
## docker-build: constrói a imagem (exige acbr-libs/)
docker-build: acbr-libs-conferir
docker build \
--build-arg APP_COMMIT=$(shell git rev-parse HEAD 2>/dev/null) \
--build-arg APP_BUILD=$(shell date -u +%Y-%m-%dT%H:%M:%SZ) \
-t $(APP_IMAGE) .
## up / down: sobe e derruba o stack (api + worker)
up: docker-build
APP_IMAGE=$(APP_IMAGE) docker compose up -d
down:
docker compose down
## limpar: remove artefatos de build
limpar:
rm -rf $(OUT)
## help: esta lista
help:
@grep -hE '^## ' $(MAKEFILE_LIST) | sed 's/^## / /' | sort
.PHONY: build build-cgo run test test-integracao-nfse test-cgo openapi openapi-check openapi-valida yaml-valida enums-conferir vet fmt fmt-check tidy limpar help \
acbr-fonte acbr-compilar acbr-extrair \
acbr-libs-baixar acbr-libs-publicar acbr-libs-conferir imagem-libs-conferir docker-build up down