From 9a45b8b0cb9235bacfdde82b4ad84a0911635c01 Mon Sep 17 00:00:00 2001 From: lvcas-dotcom <134722316+lvcas-dotcom@users.noreply.github.com> Date: Thu, 13 Aug 2026 11:40:13 -0300 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20a=20nota=20de=20release=20era=20extr?= =?UTF-8?q?a=C3=ADda,=20passada,=20e=20descartada?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit changelog.disable desliga o pipe que carrega o --release-notes. Eu liguei os dois no mesmo commit: a nota saía do CHANGELOG, chegava ao goreleaser como caminho de arquivo, e era jogada fora sem erro. A v0.1.2 foi publicada com o corpo contendo apenas o rodapé, e o release ficou verde. O pipe volta ligado. Os filtros abaixo dele nunca são usados enquanto o flag existir — estão ali para o caso de ele sumir. Duas verificações, porque a falha foi silenciosa dos dois lados. Antes de publicar, release-check falha se as duas configurações se anularem de novo, e isso roda em todo PR. Depois de publicar, o workflow busca o corpo da release e confere que ele contém a seção que passou: é o único artefato de release que ainda dá para corrigir, e essa checagem pega qualquer quebra futura do mecanismo, não só esta causa. --- .github/workflows/release.yml | 16 ++++++++++++++++ .goreleaser.yaml | 14 +++++++++++++- Makefile | 9 +++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 24c673d..310b674 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -96,3 +96,19 @@ jobs: # the wrong one: the v0.1.0 release tried to publish itself as # v0.1.0-rc.2 and died on an asset that already existed. GORELEASER_CURRENT_TAG: ${{ github.ref_name }} + + # The one published thing that can still be corrected, so it is checked + # after the fact rather than guessed at before. It exists because the + # mechanism failed silently once: the notes were extracted, passed, and + # dropped, and the release went out green with an empty body. + - name: a nota publicada é a nota escrita + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + first=$(grep -m1 . "$RELEASE_NOTES") + if ! gh release view "${{ github.ref_name }}" --json body -q .body | grep -qF "$first"; then + echo "::error::the published notes do not contain the CHANGELOG section that was passed" + gh release view "${{ github.ref_name }}" --json body -q .body + exit 1 + fi + echo "published notes carry the written section" diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 25d293e..0b85db3 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -61,8 +61,20 @@ snapshot: # --release-notes in the workflow. A list of commits says what was touched; # whoever opens a release wants to know what changed for them. See # scripts/release-notes.sh. +# +# This stage stays ENABLED even though nothing here generates the notes, and +# that is not an oversight. `--release-notes` is loaded by this pipe, so +# disabling it drops the flag on the floor: the notes never load, the body comes +# out as the footer alone, and the release still succeeds. v0.1.2 shipped that +# way. The filters below are what the flag would otherwise fall back to. changelog: - disable: true + use: git + filters: + exclude: + - "^Merge pull request" + - "^chore: arquiva" + - "^docs:" + - "^test:" # A distribution package is the shortest path for the target user: a DBA on a # Linux server, with no Go and no Homebrew. The paths below are not our choice, diff --git a/Makefile b/Makefile index cf07ae9..3da19aa 100644 --- a/Makefile +++ b/Makefile @@ -84,6 +84,15 @@ release-check: @v=$$(sed -n 's/^## \[\([0-9][^]]*\)\].*/\1/p' CHANGELOG.md | head -1); \ ./scripts/release-notes.sh "v$$v" > /dev/null; \ echo "release notes ok: $$v" +# `--release-notes` is loaded by goreleaser's changelog pipe, so disabling that +# pipe drops the flag on the floor: the notes never load, the release body comes +# out as the footer alone, and nothing fails. v0.1.2 shipped that way. + @if grep -q -- "--release-notes" .github/workflows/release.yml && \ + sed -n "/^changelog:/,/^[a-z]/p" .goreleaser.yaml | grep -qE "^[[:space:]]+disable:[[:space:]]*true"; then \ + echo "FAILED: the workflow passes --release-notes and .goreleaser.yaml disables the changelog stage that loads it"; \ + exit 1; \ + fi; \ + echo "release notes wiring ok" ## image-check: prove the image builds for both platforms # From a05336a0da1a69291792a3ff290263ceb9bd404b Mon Sep 17 00:00:00 2001 From: lvcas-dotcom <134722316+lvcas-dotcom@users.noreply.github.com> Date: Thu, 13 Aug 2026 11:40:35 -0300 Subject: [PATCH 2/2] =?UTF-8?q?docs:=20tira=20do=20README=20os=20n=C3=BAme?= =?UTF-8?q?ros=20que=20envelhecem,=20e=20fecha=20a=20quest=C3=A3o=20do=20j?= =?UTF-8?q?oin=20mining?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit O arquivo citava três versões diferentes: v0.1.1 no bloco de destaque, v0.1.1 na gravação de saída, e um .deb 0.1.0 nas instruções de instalação — apontando para um artefato que não era mais o último. Injetar a versão por build só automatizaria um problema que não precisa existir. O bloco de destaque não nomeia mais versão, porque o badge já diz pre-release e o CHANGELOG carrega as versões, e a instalação passa a usar glob. Sobra a gravação, que imprime a própria versão porque a ferramenta imprime — e sozinha no arquivo ela não contradiz nada. O risco ali não é o número envelhecer, é o formato do relatório mudar, então isso virou passo em RELEASING.md. O README dizia que era questão em aberto se o baixo rendimento da mineração de junções era dos schemas ou do extrator. Para o corpus público dá para fechar sem subir banco: o GitLab declara 336 funções e três delas contêm um JOIN, mais quinze views; o Discourse, sete funções sem nenhum JOIN e uma view. Não há o que minerar. Um structure.sql é definição de schema, e SQL analítico não mora ali. Isso agora aparece também junto da afirmação que ele relativiza, em vez de 270 linhas depois — e o link para o corpus, que estava quebrado desde antes, volta a resolver. --- README.md | 24 ++++++++++++++++++++---- docs/RELEASING.md | 16 +++++++++++----- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 04baebe..0f039f3 100644 --- a/README.md +++ b/README.md @@ -30,10 +30,10 @@ `pgfathom` finds the relationships your database has but never declared — and proves them against the data instead of guessing from column names. > [!IMPORTANT] -> **v0.1.1. Early, and measured.** +> **Early, and measured.** > `pgfathom audit` and `pgfathom discover` run end to end, verdicts and reviewable > `.sql` artifacts included, against real production schemas and against a -> [public corpus](#the-public-corpus) anyone can re-run with `make benchmark`. +> [public corpus](#the-measured-corpus) anyone can re-run with `make benchmark`. > Recovery is around 61% on a 1,857-key schema, and the report says what that > number does not measure as plainly as what it does. What the tool never does is > write to your database. The terminal output below is a real run against the @@ -126,6 +126,11 @@ Note the first row: `os_servico.resp_tecnico → funcionario.id`. No name-matchi in the world finds that one — `resp_tecnico` looks nothing like `funcionario`. `pgfathom` finds it by reading the join predicates out of your own view and function definitions. +How often that pays depends entirely on how much SQL your database stores. It is decisive +here and it recovered a single key across the public corpus, for a reason +[measured below](#the-measured-corpus): the schema dumps in it barely contain any joins to +read. A live application database is a different animal. + Output comes as a terminal report, a versioned JSON model, and reviewable `.sql` artifacts. ```console @@ -151,7 +156,7 @@ On Debian, Ubuntu, Fedora or RHEL, take the package for your architecture from t [releases](https://github.com/lvcas-dotcom/pgfathom/releases): ```console -$ sudo dpkg -i pgfathom_0.1.0_linux_amd64.deb # or: sudo rpm -i ...linux_amd64.rpm +$ sudo dpkg -i pgfathom_*_linux_amd64.deb # or: sudo rpm -i pgfathom_*_linux_amd64.rpm $ pgfathom version ``` @@ -417,7 +422,18 @@ already the language's. **Join mining contributes almost nothing measurable here**: one extra key on GitLab, none elsewhere. Reported because a feature that measured smaller than the argument for it should -say so. +say so — and because the reason turns out to be the corpus rather than the extractor. + +Count what there is to mine in these two dumps and the yield stops being surprising. GitLab +declares 336 functions, and **three of them contain a `JOIN` at all** — the rest are trigger +bodies, partition maintenance and `INSERT`/`UPDATE` on a single table. It declares 15 views. +Discourse declares 7 functions with no `JOIN` between them, and one view. A published +`structure.sql` is a schema definition, and analytical SQL is not where it lives. + +That is a fact about this corpus, not about the technique: the demo schema in +[`docs/DEMO.md`](docs/DEMO.md) recovers a relationship no name matching can reach, from one +view. What the corpus establishes is that a schema dump is a poor place to look for joins, +and that anyone quoting these numbers should say so. Three things these tables are not saying. diff --git a/docs/RELEASING.md b/docs/RELEASING.md index df41b41..c1a1a7d 100644 --- a/docs/RELEASING.md +++ b/docs/RELEASING.md @@ -44,20 +44,26 @@ pedir autenticação a quem só quer experimentar. $ scripts/release-notes.sh v0.1.2 ``` -3. Reveja `docs/benchmark/recall.md`. Os números publicados no README saem +3. Se o formato do relatório mudou nesta versão, regrave o exemplo do README. + Ele é execução real contra o schema de `docs/DEMO.md`, e o que o torna útil + é ser verdade — um exemplo que já foi verdade é pior que nenhum, porque + ninguém desconfia dele. O número de versão na gravação pode ficar para trás; + o formato não. + +4. Reveja `docs/benchmark/recall.md`. Os números publicados no README saem dali, e um release que os contradiga é pior do que um release sem eles. -4. Rode `make release-check`. Ele valida a configuração e prova que o binário +5. Rode `make release-check`. Ele valida a configuração e prova que o binário do caminho de release sabe a própria versão. -5. Rode `goreleaser release --snapshot --clean` e abra `dist/`. É a última +6. Rode `goreleaser release --snapshot --clean` e abra `dist/`. É a última chance de olhar o que vai ser publicado antes de existir uma tag. -6. Crie e empurre a tag: +7. Crie e empurre a tag: ```console $ git tag -a v0.1.0 -m 'v0.1.0' $ git push origin v0.1.0 ``` -7. O workflow roda suíte, lint e build cruzado, e só então publica. Acompanhe +8. O workflow roda suíte, lint e build cruzado, e só então publica. Acompanhe até o fim: uma falha depois da metade deixa artefatos parciais, e a resposta certa é corrigir e lançar a versão seguinte, nunca reescrever a tag.