Repository navigation
O postgresql-dev sai das três imagens depois de compilar o driver (#391) - #409
Merged
Merged
Conversation
…391) As três imagens instalavam `postgresql-dev` na lista grande de `apk add`, só para compilar o `pdo_pgsql`. O PostgreSQL 18 traz suporte a JIT, e o `-dev` dele arrasta o Clang e o LLVM 22 inteiros -- que ficavam na imagem. ## A pergunta que a issue fazia primeiro: o juiz precisa do driver? Precisa. O serviço `autojudge` do docker-compose roda `autojudge:start`, que busca as runs pendentes DIRETO no banco. Quem hospeda em PostgreSQL precisa do `pdo_pgsql` no juiz. A opção "tirar o driver" quebraria essa instalação; o que sai é o CABEÇALHO. ## O que muda - a lista de infraestrutura instala `libpq` (runtime) em vez de `postgresql-dev`; - o passo das extensões instala o `postgresql-dev` como `--virtual .pgsql-build` e o remove no MESMO `RUN`. Remover num `RUN` seguinte não economizaria nada: a camada que o instalou continuaria na imagem. ## Medido sobre a base `php:8.3-cli-alpine` (Alpine 3.24.2) perfil que corta o Clang, como era: +446 MiB, clang22 e llvm22 na imagem perfil que corta o Clang, proposto: +0 MiB, só o libpq perfil completo, como era: +446 MiB perfil completo, proposto: +306 MiB (o clang22 fica; sai o llvm22) `apk del` só remove o que nada mais exige, e no perfil que oferece Clang o `clang22` está em /etc/apk/world e sobrevive -- que é o correto. Conferido no contêiner, e não suposto: - `pdo_pgsql` compila, `php -m` o lista, e `libpq.so.5` resolve para `/usr/lib/libpq.so.5`; - um `new PDO("pgsql:...")` contra uma porta fechada devolve `Connection refused` -- erro de CONEXÃO, e não "could not find driver"; - os comandos EXATOS de `c_clang17` e `cpp_clang` do catálogo (`-static`, `-std=c17` / `-std=c++20`, `-lm`) compilam, linkam estático e rodam sem o `llvm22`; - os `pecl install redis` e `pcov` que vêm DEPOIS da remoção ainda constroem e carregam. ## A guarda `PostgresqlDevSoNaCompilacaoTest`, nas três imagens, lendo o Dockerfile na granularidade de instrução (continuações juntadas, comentários fora): 1. `postgresql-dev` só como `--virtual`, removido no mesmo RUN; 2. o `libpq` de runtime continua num `apk add` persistente; 3. o `pdo_pgsql` continua sendo compilado. Mutação, uma por guarda, contra o `Dockerfile.judge`: tiro o `apk del` -> 1 falha devolvo o `postgresql-dev` à lista -> 1 falha tiro o `libpq` -> 1 falha tiro o `pdo_pgsql` da compilação -> 1 falha restaurado -> OK (9 testes) `tests/Unit` e `tests/Feature` passam (1886 testes). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
O commit anterior deste PR derrubou o check "Os pinos das três imagens
resolvem no Alpine de hoje". Não foi pino morto: foi o parser.
`DockerfileToolchain::apkPackages()` -- o mesmo que as guardas e o
`pinos-alpine.yml` usam -- tratava como lista de pacotes TODO token depois
de `apk add` até o fim da instrução. O `RUN` novo deste PR,
apk add --virtual .pgsql-build postgresql-dev \
&& docker-php-ext-install ... pdo_pgsql ... \
&& apk del .pgsql-build
virou uma "lista" com `&&`, `apk`, `del`, `docker-php-ext-install` e
`pdo_pgsql`, e o `apk add --simulate` do workflow recusou.
O defeito era latente: nenhuma linha de `apk` do repositório tinha `&&` nem
`--virtual`, então nunca tinha disparado. As guardas passaram verdes -- lendo
lixo em silêncio.
## Três regras
1. o comando termina no primeiro separador de shell (`&&`, `||`, `;`, `|`);
2. opção com argumento (`--virtual NOME`, `--repository URL`, ...) consome
o token seguinte: o nome do grupo não é pacote;
3. um grupo `--virtual` removido com `apk del` no MESMO `RUN` não chega à
imagem final, então não é pacote dela. Sem o `apk del`, os pacotes ficam
-- senão a regra esconderia o erro de esquecer a remoção, que é o erro
que a #391 corrige.
O parser agora lê a instrução inteira (continuações juntadas, comentários
fora), que é o que o Docker executa.
## Conferido
- **sem regressão**: nos três Dockerfiles do `master`, o parser novo dá
EXATAMENTE a mesma lista que o antigo (60, 59 e 62 pacotes, byte a byte);
- nos Dockerfiles deste PR, a única diferença para o `master` é
`-postgresql-dev +libpq`, nos três;
- o `apk add --simulate` do workflow, reproduzido localmente em bash com a
mesma extração: as três imagens resolvem;
- quatro testes novos, um por regra e um para o contrário da regra 3.
Mutação, uma de cada vez: tirar a parada no separador, não consumir o
argumento, não descartar o grupo removido, descartar pelo `--virtual`
sozinho -- cada uma reprova;
- `tests/Unit` e `tests/Feature` passam.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
matbrgz
added a commit
that referenced
this pull request
Sep 25, 2026
…ara de quebrar a cada revisão (#408) (#411) * O pino do Alpine passa a prometer o que o rótulo promete, e o build para de quebrar a cada revisão (#408) A #303 fixou todo toolchain por `pacote=versão-rN`. O Alpine não guarda revisões antigas: quando publica a próxima, a fixada some e o build sem cache para em `unable to select packages`. Foram três em menos de um dia -- `erlang27` na 27.3.4.17-r0, `perl` na 5.42.2-r0 (só recompilação do Alpine, mesma versão) e `ocaml` na 4.14.3-r0. Decisão do mantenedor na #408: opção (b) agora, publicar por digest (c) depois. ## O operador `~` do `apk`, que casa POR COMPONENTE. Medido no Alpine de hoje: perl=5.42.2-r0 morto perl~5 resolve ocaml=4.14.3-r0 morto ocaml~4.14 resolve rust~1.9 NAO casa com 1.96.1 gcc~1 NAO casa com 15 ocaml~4.15, perl~6, python3~3.15 recusados Afrouxar não deixa entrar versão que o rótulo não anuncia. ## A regra, calculada e não escrita à mão - o pacote que É o executável que a sonda de versão de uma linguagem mede (`ToolchainVersions`) fica na granularidade que o rótulo promete: `python3~3.14`, `nodejs~24`, `gcc~15`, `perl~5` -- 28 pacotes; - o resto (bibliotecas, `bash`, `bubblewrap`, `npm`) fica em `~MAJOR.MINOR` -- 12 pacotes. "É o executável" quer dizer o PRIMEIRO requisito da procedência. A sonda do Kotlin mede o `kotlinc`, que roda na JVM do `openjdk21-jdk`; o "2.4" do rótulo é do Kotlin, não da JVM. A primeira versão do cálculo, sem essa distinção, dava à mesma JVM três promessas (21, 2.4, 1.12), e ao `gmp` o "10" do SWI-Prolog. Com ela: 40 pinos, zero conflitos, e todos casam com a versão instalada hoje. ## Onze leitores de `nome=pino`, e um que teria falhado em silêncio `docker/judge/perfil/perfil` extraía o nome com `${arg%%=*}`. Com `perl~5` o "nome" virava `perl~5`, o corte `apk:perl` não casava, e o perfil `maratona` -- que corta perl, ocaml e ghc -- instalaria os três, GHC inteiro, sem erro. Demonstrado antes do conserto: perfil filtra git perl~5 ocaml~4.14 ghc~9.10 -> todos passam depois do conserto -> git (os três cortados) Conferido no `sh` do Alpine (busybox), que é o que roda no `RUN`. O `ImagemPorPerfilTest` roda esse script de verdade -- mas montava os tokens com `nome=pino` à mão, e por isso NÃO pegaria o defeito. Passou a usar os tokens reais da linha; revertendo o script, ele reprova. Os outros: o parser ganhou `apkSpecs()` e `specFor()`, que devolvem o token exato com o operador, e cinco lugares que montavam `alvo.'='.pinFor()` -- e transformariam `perl~5` em `perl=5`, que o `apk` lê como "exatamente a versão 5" -- passaram a usá-los: `ToolchainManifest::resolvedPackagesFor`, `judge:toolchain-profile`, o workflow `pinos-alpine.yml` e dois testes. ## A guarda `PinoNaGranularidadeDaPromessaTest`, nas três imagens: nenhum pino exato; o pacote de cada linguagem na granularidade exata do rótulo; o resto em `MAJOR.MINOR`; e nenhum pacote com duas promessas. Mutação, uma por vez: volto `perl=5.42.2-r1` -> 2 falhas `gcc~15.2` (mais fino) -> 1 falha `python3~3` (mais frouxo) -> 1 falha `zlib~1` (fora de major.minor) -> 1 falha script `perfil` revertido -> ImagemPorPerfilTest reprova ## O que "reprodutível" passa a querer dizer Antes: (commit, perfil) -> toolchains idênticos. Agora: (commit, perfil) -> a versão do upstream que o rótulo promete, e o patch exato de cada veredito fica gravado no julgamento (#402). O inventário diz isso onde a tabela de pinos começa. ## Conferido - `apk add --simulate` das três imagens, com a mesma extração do workflow: 60, 59 e 62 pacotes, resolvem; - `tests/Unit` e `tests/Feature`: 1900 testes. Empilhado sobre o #409 (o parser que sabe onde termina um `apk add`). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Estilo: o Pint alinha o docblock do teste novo (#408) O job Backend roda o Pint nos arquivos novos, e o PinoNaGranularidadeDaPromessaTest tinha um espaço duplo no @return. Só espaço em branco. Conferido o Pint em todos os PHP que o PR toca. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Estilo: o Pint formata os métodos novos do parser (#408) O job Backend só confere o Pint nos arquivos NOVOS, e por isso não pegou o `DockerfileToolchain.php`, que é modificado. Conferido que o problema era deste PR: no `master` o arquivo passa, aqui não passava. A diferença é só espaço em branco (`git diff -w` vazio). Pint verde em todos os PHP do PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #391.
A primeira pergunta da issue: o juiz precisa do driver?
Precisa. O serviço
autojudgedodocker-compose.ymlrodaautojudge:start, que busca as runs pendentes direto no banco (depends_on: db). Quem hospeda em PostgreSQL precisa dopdo_pgsqlno juiz. A saída (3) da issue — "conferir se o juiz precisa depdo_pgsqlde todo" — quebraria essa instalação. O que sai é o cabeçalho, não o driver.A mudança
Nas três imagens:
libpq(runtime) em vez depostgresql-dev;postgresql-devcomo--virtual .pgsql-builde o remove no mesmoRUN. Remover numRUNseguinte não economizaria nada: a camada que o instalou continuaria na imagem, com o LLVM dentro.É a saída (1) da issue.
Medido
Sobre a base real,
php:8.3-cli-alpine(Alpine 3.24.2):maratona)clang22,llvm22,llvm22-libs,clang22-libscompletollvm22(as ferramentas); oclang22ficaapk delsó remove o que nada mais exige. No perfil que oferece Clang oclang22está em/etc/apk/worlde sobrevive — que é o correto.Conferido no contêiner, e não suposto
pdo_pgsqlcompila, aparece emphp -m, elibpq.so.5 => /usr/lib/libpq.so.5. Umnew PDO("pgsql:...")contra uma porta fechada devolveConnection refused— erro de conexão, não "could not find driver";llvm22: os comandos exatos do catálogo compilam, linkam estático e rodam:pecl install redisepecl install pcovrodam depois doapk delnas imagens, e poderiam depender dosopenssl-dev/lz4-dev/zstd-devque o grupo leva embora. Replicada a sequência inteira: os dois constroem e carregam.A guarda
tests/Unit/Judge/PostgresqlDevSoNaCompilacaoTest.php, nas três imagens, lendo o Dockerfile na granularidade de instrução (continuações juntadas, comentários fora — o que o Docker faz antes de executar):postgresql-devsó como--virtual, removido no mesmoRUN;libpqcontinua numapk addpersistente — senão o driver compila e não carrega;pdo_pgsqlcontinua sendo compilado — o conserto não pode virar "tirar o driver".Mutação, uma por guarda, contra o
Dockerfile.judge:tests/Unitetests/Feature: 1886 testes, verdes.O que a medição não cobre
completopode diferir se algum outro pacote da lista também exigir ollvm22.maratonao Clang some" se apoia noapk info -r clang22que a issue mediu na imagem real (só opostgresql18-devo exige) e na reprodução acima. O CI constrói o perfilcompleto, então essa parte não é conferida pelo job.docs/specs/306-perfis-de-toolchain.mdganhou a nota de resolução no parágrafo que tinha registrado o achado e o mandado para cá.🤖 Generated with Claude Code