Python e Postgres divergem sobre o que significa "CET" e quebram queries de merge-freeze do Mergify
Aprofundamento CEVIU
Aprofundamento
O caso do Mergify mostra dois bugs com a mesma origem: duas aplicações lendo a mesma coluna com bancos de fusos diferentes. Um usuário criou um merge-freeze agendado com o fuso localtime, a API devolveu 201 e, a partir daí, todo pull request do repositório falhou na avaliação. O engine tentava de novo a cada 12 segundos, e essa única linha respondeu por 313 de cerca de 344 erros na hora em que o alerta de 300 erros por hora disparou.
A API validava o nome contra zoneinfo.available_timezones(), que só reflete o Python. A imagem do engine roda Debian trixie com tzdata-legacy e dá 599 nomes ao Python. O Postgres de produção, no Cloud SQL, conhece 597. Os dois que ele recusa são localtime e Factory. Já CET, EET, MET e WET convertem sem erro nos dois lados, mas o AT TIME ZONE do Postgres consulta primeiro a tabela de abreviações, onde CET é +01:00 fixo, sem horário de verão. No Python, CET tem verão. Resultado: uma hora de diferença entre fim de março e fim de outubro, sem erro nem log. Nenhum freeze armazenado usava esses nomes, então esse bug nunca afetou ninguém.
A correção foi um campo pydantic, PostgresTimeZone, que aceita o que o Python conhece menos seis nomes. Um teste de paridade compara, para janeiro e julho, o instante convertido por Postgres e por ZoneInfo. O Postgres de teste conhece 487 nomes e o teste exige que mais de 400 passem pelo filtro. O autor validou o campo contra os 19 nomes distintos de 150 freezes em produção, e todos passaram, incluindo Asia/Calcutta, alias legado que o Chrome ainda reporta para a Índia. A equipe também descartou remover o tzdata-legacy, porque o NEWS do Debian recomenda o pacote para sistemas que servem dados de fuso pela rede, como bancos SQL. A correção entrou em 28 de setembro.
Por que isso importa
Para quem opera API em Python sobre Postgres, a leitura é: validar entrada contra um runtime só deixa passar divergências silenciosas. O erro que derruba é o menos perigoso. O que desloca um agendamento em uma hora sem avisar é pior. Uma lista única, imposta por teste de integração que compara os dois lados, custa pouco e evita dependência do banco na subida dos workers. Vale lembrar que o teste não pega mudança de tzdata no Cloud SQL, e que condições de configuração como schedule=…[US/Central] ainda aceitam qualquer nome do Python.
Linha do tempo
Mergify faz merge da correção com o campo PostgresTimeZone e o teste de paridade.
CEVIU noticia a divergência entre Python e Postgres sobre CET e a correção do Mergify.
Perguntas frequentes
Por que Python e Postgres tratam CET de forma diferente?
No Python, CET é uma zona com horário de verão. No Postgres, o AT TIME ZONE procura o nome primeiro na tabela de abreviações, onde CET é um deslocamento fixo de +01:00. Entre fim de março e fim de outubro, os dois resultados diferem em uma hora. O mesmo vale para EET, MET e WET.
Quais nomes o Mergify passou a recusar?
Seis: localtime, Factory, CET, EET, MET e WET. Os dois primeiros quebram queries no Postgres de produção. Os quatro últimos convertem sem erro, mas com uma hora de diferença no verão. A mensagem de erro orienta a escolher uma cidade no formato Zone/City.
Por que não validar perguntando ao Postgres a cada criação?
Exigiria uma ida ao banco em cada create e update, e o Postgres aceita CET sem reclamar, então não pegaria os quatro nomes que divergem. A equipe também descartou consultar o Postgres na inicialização, porque todos os workers se conectariam juntos no redeploy.
Por que manter o tzdata-legacy na imagem?
O pacote é só uma divisão de empacotamento do Debian desde o trixie, e o NEWS do Debian recomenda instalá-lo quando o sistema fornece dados com fuso pela rede, como bancos SQL. Além disso, localtime e Factory continuariam existindo sem ele. Aliases como Asia/Calcutta também precisam seguir aceitos.
Fontes
- mergify.comfonte original
- Categoria
- CEVIU Web Dev
- Publicado
- 27 de outubro de 2026
- Editoria
- CEVIU Web Dev

