Repository navigation
Conversation
EvidênciaRodado no head do PR ( Caso na base (
|
| Caso | Esperado | Obtido |
|---|---|---|
uses: por tag |
29 na base, 0 no ramo | 29 → 0. No ramo, as 29 linhas uses: casam com @[0-9a-f]{40} # vX.Y.Z |
| SHA de cada action | o commit da tag usada na base e o da tag do comentário são o SHA fixado | 7 de 7, por gh api repos/<dono>/<action>/commits/<tag> (bloco abaixo) |
actions/checkout sem persist-credentials: false |
8 na base, 0 no ramo | 8 → 0 (7 em tests.yml, 1 em docs.yml) |
| Passo que dependa da credencial do checkout | nenhum | grep -rnE 'git (push|fetch|pull|clone)|GITHUB_TOKEN|github\.token|(^|[^a-z])gh ' .github src tests mkdocs.yml pyproject.toml sem ocorrência na base e no ramo |
Permissões do docs.yml |
workflow só com contents: read; deploy com pages: write e id-token: write; build herda contents: read |
igual no ramo. Na base, o workflow tinha as três e os dois jobs herdavam |
Permissões do tests.yml |
contents: read no workflow, nenhum job com bloco próprio |
igual na base e no ramo |
Passo zizmor no job quality |
reprova a base, passa no ramo | código 14 em b1707f26 (local), 0 em b5b4e02f (local e no CI) |
| Workflows válidos | actionlint sem erro | uvx --from actionlint-py@1.7.12.25 actionlint -shellcheck= .github/workflows/*.yml com código 0 na base e no ramo |
| Nada fora dos workflows e da documentação mudou | src, tests, pyproject.toml e uv.lock idênticos à base |
git diff --stat origin/main -- src tests pyproject.toml uv.lock vazio; o diff toca só docs.yml, tests.yml, CHANGELOG.md e CONTRIBUTING.md |
Os casos de checkout e de permissões foram lidos com yaml.safe_load dos dois workflows: para cada passo com uses: actions/checkout@..., se with.persist-credentials é False; e o bloco permissions do workflow e de cada job.
SHA fixado contra as tags, pela API do GitHub
$ paste -d' ' \
<(git show origin/main:.github/workflows/tests.yml origin/main:.github/workflows/docs.yml | grep -oE 'uses: [^ ]+') \
<(cat .github/workflows/tests.yml .github/workflows/docs.yml | grep -oE 'uses: [^ ]+ # v[0-9.]+') \
| sort -u | while read -r _ antigo _ novo _ versao; do
repo=${novo%@*}; sha=${novo#*@}; tag=${antigo#*@}
echo "$repo $sha $versao:$(gh api repos/$repo/commits/$versao --jq .sha) $tag:$(gh api repos/$repo/commits/$tag --jq .sha)"
done
actions/checkout 3d3c42e5aac5ba805825da76410c181273ba90b1 v7.0.1:3d3c42e5aac5ba805825da76410c181273ba90b1 v7:3d3c42e5aac5ba805825da76410c181273ba90b1
actions/deploy-pages 368f82528645a54fb793d4d04e342629a3f51346 v5.0.1:368f82528645a54fb793d4d04e342629a3f51346 v5:368f82528645a54fb793d4d04e342629a3f51346
actions/download-artifact 9000827ccba6bdab643e8b6fd33ac0654aef8333 v8.0.2:9000827ccba6bdab643e8b6fd33ac0654aef8333 v8:9000827ccba6bdab643e8b6fd33ac0654aef8333
actions/setup-python 5fda3b95a4ea91299a34e894583c3862153e4b97 v7.0.0:5fda3b95a4ea91299a34e894583c3862153e4b97 v7:5fda3b95a4ea91299a34e894583c3862153e4b97
actions/upload-artifact cf430e030ddbb5b0abf93d22962f4752f3646cd9 v7.0.2:cf430e030ddbb5b0abf93d22962f4752f3646cd9 v7:cf430e030ddbb5b0abf93d22962f4752f3646cd9
actions/upload-pages-artifact fc324d3547104276b827a68afc52ff2a11cc49c9 v5.0.0:fc324d3547104276b827a68afc52ff2a11cc49c9 v5:fc324d3547104276b827a68afc52ff2a11cc49c9
astral-sh/setup-uv c18668ad3cf93ea998bef934396af7bb5c839dc7 v10.2.0:c18668ad3cf93ea998bef934396af7bb5c839dc7 v10.2.0:c18668ad3cf93ea998bef934396af7bb5c839dc7
Testes
Base (b48bd034) |
Ramo (b5b4e02f) |
|
|---|---|---|
Suíte inteira, Python 3.11, todos os extras: uv run --python 3.11 --extra dev --extra all --extra search-all --extra polars --extra excel --extra codex pytest --cov=dataframeit --cov-branch |
1760 passados, 0 pulados; cobertura 99,96% (código 1 pelo fail_under = 100) |
1760 passados, 0 pulados; cobertura 99,96% (código 1 pelo fail_under = 100) |
Job unit do CI: uv run --python 3.11 --extra dev --extra all --extra search-all pytest --cov=dataframeit --cov-branch --cov-report= --cov-fail-under=0, venv sem o extra codex |
1599 passados, 129 pulados | 1599 passados, 129 pulados |
Job codex-provider do CI: uv run --python 3.11 --extra dev --extra codex pytest --cov=dataframeit --cov-branch --cov-report= --cov-fail-under=0 |
1393 passados, 367 pulados | 1393 passados, 367 pulados |
Job coverage do CI: coverage combine dos dois anteriores e coverage report |
TOTAL 3298 0 1312 0 100%, código 0 |
TOTAL 3298 0 1312 0 100%, código 0 |
Gates do job quality, Python 3.13 com os extras do job: ruff format --check src tests, ruff check src tests, ty check, vulture, deptry src |
código 0 nos cinco | código 0 nos cinco |
uv run --python 3.13 --extra docs mkdocs build (o CHANGELOG.md entra no site) |
código 0, 2 avisos do mkdocs_static_i18n sobre navigation.instant |
código 0, os mesmos 2 avisos |
Na suíte num ambiente só, a cobertura fica em 99,96% na base e no ramo porque as linhas 700 e 701 de src/dataframeit/codex.py, o except ImportError do import de openai_codex.errors, só rodam sem o extra codex instalado. A combinação que o CI faz cobre as duas e chega a 100%. Cada configuração rodou num venv próprio, com o dataframeit importado do src da árvore em teste.
No CI do PR (run 39703038888, head b5b4e02f), os 10 jobs passaram. O job coverage baixou os 4 artefatos pelo download-artifact já fixado, combinou os 4 arquivos e imprimiu TOTAL 3298 0 1312 0 100%.
Risco: a parte que o CI do PR não roda é o docs.yml, que dispara só em push na main e em workflow_dispatch. O PR toca docs.yml e CHANGELOG.md, que estão no paths do gatilho, e por isso o push do merge roda o build sem credencial gravada e o deploy com as permissões só dele pela primeira vez. Se o deploy falhar por permissão, o site fica na versão anterior, sem efeito para quem usa a biblioteca. Desfazer: git revert do merge, ou devolver pages: write e id-token: write ao nível do workflow. Uma action futura que dependa da credencial gravada pelo checkout falha no passo que a usa, e o conserto é ligar persist-credentials só naquele checkout. As actions fixadas continuam com atualização pelo Dependabot, que tem a entrada github-actions no dependabot.yml; a versão do zizmor, escrita dentro de run:, sobe à mão.
SHA revisado: b5b4e02
O zizmor --offline reprova a action referida por tag ou branch no lugar do SHA, o actions/checkout sem a chave persist-credentials e a permissão de escrita no nível do workflow. Ele não confere o comentário de versão e aceita persist-credentials: true, e o CONTRIBUTING passa a dizer que essas duas partes da convenção ficam com a revisão do PR. O comentário do passo zizmor troca a razão do --offline pela verdadeira, as consultas à API do GitHub a cada execução, e nomeia as cinco auditorias que ficam de fora. O .pre-commit-config.yaml deixa de dizer que src/ e tests/ são as únicas pastas que o CI confere.
Revisão independenteA revisão foi feita por três subagentes do Claude sobre o SHA Corrigido em
Descartado: o comando audita só Preexistente, aberto como issue: #268. Nenhum check de PR confere as permissões do job que publica a documentação. Não executado:
O merge deste PR dispara o deploy da documentação, porque toca |
Problema
Na
mainde agora (b48bd03),uvx zizmor@1.30.1 --offline .github/workflowsacusa 39 achados e sai com código 14:unpinned-uses: as 29 linhasuses:dos dois workflows citam a action por tag (actions/checkout@v7,astral-sh/setup-uv@v10.2.0e as outras cinco). O dono da action pode mover a tag para outro commit, e o workflow passa a rodar código que ninguém revisou.artipacked: nenhum dos 8actions/checkouttempersist-credentials: false, e o token do GitHub fica no.git/configdo runner durante o job. Os jobsunitecodex-providersobem artefato.excessive-permissions:pages: writeeid-token: write, no nível dodocs.yml, valem também para o jobbuild, que roda o código do repositório e não publica nada.O que muda
Os quatro itens da proposta da issue estão corrigidos, e o zizmor passa a sair com zero achados e código 0.
Actions fixadas pelo commit. Cada
uses:aponta para o SHA, com a versão em comentário:actions/checkoutv73d3c42e5aac5ba805825da76410c181273ba90b1# v7.0.1actions/setup-pythonv75fda3b95a4ea91299a34e894583c3862153e4b97# v7.0.0astral-sh/setup-uvv10.2.0c18668ad3cf93ea998bef934396af7bb5c839dc7# v10.2.0actions/upload-artifactv7cf430e030ddbb5b0abf93d22962f4752f3646cd9# v7.0.2actions/download-artifactv89000827ccba6bdab643e8b6fd33ac0654aef8333# v8.0.2actions/upload-pages-artifactv5fc324d3547104276b827a68afc52ff2a11cc49c9# v5.0.0actions/deploy-pagesv5368f82528645a54fb793d4d04e342629a3f51346# v5.0.1Cada SHA veio de
gh api repos/<dono>/<action>/git/ref/tags/<tag>. As sete tags são leves, então o objeto do ref já é o commit, e a tag de versão do comentário aponta para o mesmo commit da tag usada.Checkout sem credencial gravada.
persist-credentials: falsenos 8 checkouts. Nenhum passo usa essa credencial: os passos rodam uv, ruff, ty, vulture, deptry, pytest, coverage, mkdocs ecp, e odeploy-pagesse autentica com o token OIDC no jobdeploy, que não faz checkout.Permissões do Pages só no deploy. No
docs.yml,contents: readfica no nível do workflow, epages: writeeid-token: writepassam para o jobdeploy. Permissão declarada no job substitui a do workflow, e odeploydeixa de recebercontents: read, que ele não usa.zizmor no job
quality. Passo novo, antes do ruff:uvx zizmor@1.30.1 --offline .github/workflows. Nenhum achado precisou ser ignorado na configuração. Os 15 achados que só as personaspedanticeauditormostram, comotemplate-injectiondematrix.python-versioneanonymous-definition, ficam fora da persona padrão e têm a mesma contagem por tipo na base e no ramo.O
CHANGELOG.mdganha a entrada emSegurança, e oCONTRIBUTING.mddiz que o CI roda o zizmor e que action nova entra fixada pelo SHA, compersist-credentials: falseno checkout.Decisões
# v7.0.1), e não com a tag móvel (# v7). É a forma que o próprio Dependabot escreve quando sobe um SHA fixado: oVersionCommentermonta o comentário commost_specific_version_tag_for_sha. Com isso, o primeiro PR dele não troca o formato do comentário, e quem lê o workflow vê qual release o SHA é.cooldowndodependabot.yml. A 1.31.1 também dá zero achados no ramo. O Dependabot não atualiza versão escrita dentro derun:, e por isso a subida do zizmor é manual; o comentário do passo diz isso.--offline. As auditorias online do zizmor consultam a API do GitHub e precisariam de token no job. A correspondência entre SHA e tag, que uma delas confere, foi verificada pela API na preparação deste PR.O que o CI deste PR não exercita
O
docs.ymlroda só em push namaine emworkflow_dispatch. As permissões novas do jobdeploye o checkout sem credencial do jobbuildnão rodam neste PR. Como o PR tocadocs.ymleCHANGELOG.md, que estão nopathsdo gatilho, o push do merge dispara o deploy, e é nele que essa parte roda pela primeira vez.Closes #209