chore: cap logo PNGs at 512px and enforce it in CI - #238
Conversation
`ci/validate_modules.sh` only ever ran pngquant and compared byte sizes, so a large-but-well-quantized icon passed cleanly. That let 1024x1024 (and one 2048x2048, 2 MB) logos into the repo unnoticed. Add a dimension check alongside the existing minimization check: - Reject buildingblock PNGs larger than 512px in either dimension. - Read width/height straight from the PNG IHDR chunk so validation needs no image tooling; ImageMagick is only required by --fix. - --fix resizes with Lanczos using `512x512>`, so it only ever shrinks and preserves aspect ratio for non-square banners. - Run the dimension check before minimization so a file resized by --fix gets re-minimized in the same pass. - Error out when pngquant is missing instead of silently passing every PNG. Resize and re-optimize the 8 offending logos, and optimize the remaining stackit PNGs while in there. Biggest wins: aws/alternate-contacts 2064762 -> 137145 bytes and azuredevops/agent-pool 572655 -> 128914 bytes; about 2.3 MB removed overall. All resized icons were compared against the originals and are visually unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Scorecard Check
|
| Module | Overall | Core Structure | Integration | Azure Backplane | STACKIT Backplane | Testing |
|---|---|---|---|---|---|---|
aks/postgresql |
🟡 70% | 🟢 86% | n/a | n/a | n/a | 🔴 33% |
aws/alternate-contacts |
🟡 60% | 🟡 71% | n/a | n/a | n/a | 🔴 33% |
azure/spoke-network |
🟡 58% | 🟢 86% | n/a | 🔴 44% | n/a | 🔴 33% |
azuredevops/agent-pool |
🟡 70% | 🟢 86% | n/a | n/a | n/a | 🔴 33% |
ske/ske-starterkit |
🟢 91% | 🟢 100% | 🟢 92% | n/a | n/a | 🟡 67% |
stackit/git-repository |
🟢 88% | 🟢 100% | 🟢 100% | n/a | 🔴 25% | 🟢 100% |
stackit/network |
🟢 92% | 🟢 100% | 🟢 100% | n/a | 🟢 100% | 🔴 33% |
stackit/network-area |
🟢 92% | 🟢 100% | 🟢 100% | n/a | 🟢 100% | 🔴 33% |
stackit/project |
🟢 81% | 🟢 100% | 🟡 79% | n/a | 🟢 100% | 🔴 33% |
stackit/storage-bucket |
🟢 100% | 🟢 100% | 🟢 100% | n/a | 🟢 100% | 🟢 100% |
⚠️ 9 modules have failing checks — failing categories are expanded below.
Core Structure — some checks failing
Basic module file structure and documentation — applies to 10 modules
| Module | Score | 📦 | 🔗 | 📋 | 📝 | 🖼️ | 📌 | 🔒 |
|---|---|---|---|---|---|---|---|---|
aks/postgresql |
🟢 86% | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
aws/alternate-contacts |
🟡 71% | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ |
azure/spoke-network |
🟢 86% | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
azuredevops/agent-pool |
🟢 86% | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
ske/ske-starterkit |
🟢 100% | ✅ | ✅ | ➖ | ✅ | ✅ | ✅ | ✅ |
stackit/git-repository |
🟢 100% | ✅ | ✅ | ➖ | ✅ | ✅ | ✅ | ✅ |
stackit/network |
🟢 100% | ✅ | ✅ | ➖ | ✅ | ✅ | ✅ | ✅ |
stackit/network-area |
🟢 100% | ✅ | ✅ | ➖ | ✅ | ✅ | ✅ | ✅ |
stackit/project |
🟢 100% | ✅ | ✅ | ➖ | ✅ | ✅ | ✅ | ✅ |
stackit/storage-bucket |
🟢 100% | ✅ | ✅ | ➖ | ✅ | ✅ | ✅ | ✅ |
Core Structure — Summary
| Emoji | Criterion | Coverage | Status |
|---|---|---|---|
| 📦 | buildingblock/ directory exists | 10/10 | 🟢 100% |
| 🔗 | meshstack_integration.tf present | 6/10 | 🟡 60% |
| 📋 | buildingblock/APP_TEAM_README.md present (no-integration fallback) | 3/4 | 🟡 75% |
| 📝 | buildingblock/README.md with YAML front-matter | 10/10 | 🟢 100% |
| 🖼️ | buildingblock/logo.png included | 10/10 | 🟢 100% |
| 📌 | buildingblock/versions.tf present | 10/10 | 🟢 100% |
| 🔒 | Provider versions use minimum constraint (>=) | 10/10 | 🟢 100% |
Integration — some checks failing
meshstack_integration.tf conventions — applies to 6 modules
| Module | Score | 🏷️ | 🏢 | 📤 | 🔌 | 📎 | 🔀 | 📋 | 🏷️ | 🧱 | 📖 | 📝 | 📊 | 🚫 | 🔄 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ske/ske-starterkit |
🟢 92% | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ➖ |
stackit/git-repository |
🟢 100% | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ➖ |
stackit/network |
🟢 100% | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ➖ |
stackit/network-area |
🟢 100% | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ➖ |
stackit/project |
🟡 79% | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ |
stackit/storage-bucket |
🟢 100% | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ➖ |
Integration — Summary
| Emoji | Criterion | Coverage | Status |
|---|---|---|---|
| 🏷️ | variable "hub" in integration | 6/6 | 🟢 100% |
| 🏢 | variable "meshstack" in integration | 6/6 | 🟢 100% |
| 📤 | building_block_definition output exposed | 6/6 | 🟢 100% |
| 🔌 | meshcloud/meshstack in required_providers | 6/6 | 🟢 100% |
| 📎 | backplane source uses var.hub.git_ref | 6/6 | 🟢 100% |
| 🔀 | ref_name uses var.hub.git_ref | 6/6 | 🟢 100% |
| 📋 | version_spec.draft uses var.hub.bbd_draft | 6/6 | 🟢 100% |
| 🏷️ | BBD metadata.tags forwards var.meshstack.tags | 6/6 | 🟢 100% |
| 🧱 | BBD input argument vars with optional() have explicit defaults | 5/6 | 🟢 83% |
| 📖 | BBD readme field present | 5/6 | 🟢 83% |
| 📝 | BBD readme starts with plain-text description (no heading) | 5/6 | 🟢 83% |
| 📊 | BBD readme has shared responsibility table (✅/❌) | 5/6 | 🟢 83% |
| 🚫 | No documentation_md output in backplane | 6/6 | 🟢 100% |
| 🔄 | meshstack_platform has lifecycle ignore_changes = [availability] | 1/1 | 🟢 100% |
Azure Backplane — some checks failing
Azure UAMI-based automation principal conventions — applies to 1 modules
| Module | Score | 🪪 | 🚫 | 🚫 | 🔑 | 🔗 | ⚡ | 🧹 | 📤 | 📍 |
|---|---|---|---|---|---|---|---|---|---|---|
azure/spoke-network |
🔴 44% | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
Azure Backplane — Summary
| Emoji | Criterion | Coverage | Status |
|---|---|---|---|
| 🪪 | Uses azurerm_user_assigned_identity | 0/1 | 🔴 0% |
| 🚫 | No azuread_application resources | 1/1 | 🟢 100% |
| 🚫 | No azuread_service_principal resources | 1/1 | 🟢 100% |
| 🔑 | No azuread_application_password resources | 1/1 | 🟢 100% |
| 🔗 | Uses azurerm_federated_identity_credential | 0/1 | 🔴 0% |
| ⚡ | workload_identity_federation is non-nullable | 0/1 | 🔴 0% |
| 🧹 | No create_service_principal_name toggle | 1/1 | 🟢 100% |
| 📤 | Outputs identity (client_id, principal_id, tenant_id) | 0/1 | 🔴 0% |
| 📍 | Integration has azure_location | 0/1 | 🔴 0% |
STACKIT Backplane — some checks failing
STACKIT WIF-based automation principal conventions — applies to 5 modules
| Module | Score | 🔐 | 🚫 | 📤 | ⚡ |
|---|---|---|---|---|---|
stackit/git-repository |
🔴 25% | ❌ | ✅ | ❌ | ❌ |
stackit/network |
🟢 100% | ✅ | ✅ | ✅ | ✅ |
stackit/network-area |
🟢 100% | ✅ | ✅ | ✅ | ✅ |
stackit/project |
🟢 100% | ✅ | ✅ | ✅ | ✅ |
stackit/storage-bucket |
🟢 100% | ✅ | ✅ | ✅ | ✅ |
STACKIT Backplane — Summary
| Emoji | Criterion | Coverage | Status |
|---|---|---|---|
| 🔐 | Uses stackit_service_account_federated_identity_provider | 4/5 | 🟢 80% |
| 🚫 | No stackit_service_account_key resource | 5/5 | 🟢 100% |
| 📤 | Outputs service_account_email (not key) | 4/5 | 🟢 80% |
| ⚡ | Buildingblock provider uses use_oidc = true | 4/5 | 🟢 80% |
Testing — some checks failing
End-to-end test coverage — applies to 10 modules
| Module | Score | ⚙️ | 🧪 | ✅ |
|---|---|---|---|---|
aks/postgresql |
🔴 33% | ✅ | ❌ | ❌ |
aws/alternate-contacts |
🔴 33% | ✅ | ❌ | ❌ |
azure/spoke-network |
🔴 33% | ✅ | ❌ | ❌ |
azuredevops/agent-pool |
🔴 33% | ✅ | ❌ | ❌ |
ske/ske-starterkit |
🟡 67% | ❌ | ✅ | ✅ |
stackit/git-repository |
🟢 100% | ✅ | ✅ | ✅ |
stackit/network |
🔴 33% | ✅ | ❌ | ❌ |
stackit/network-area |
🔴 33% | ✅ | ❌ | ❌ |
stackit/project |
🔴 33% | ✅ | ❌ | ❌ |
stackit/storage-bucket |
🟢 100% | ✅ | ✅ | ✅ |
Testing — Summary
| Emoji | Criterion | Coverage | Status |
|---|---|---|---|
| ⚙️ | backplane/ directory (optional tier) | 9/10 | 🟢 90% |
| 🧪 | e2e/ test directory exists | 3/10 | 🔴 30% |
| ✅ | e2e/ contains .tftest.hcl files | 3/10 | 🔴 30% |
📈 Overall Summary
Overall Average Score: 80%
Score Distribution
- 🟢 High maturity (≥80%): 6 modules
- 🟡 Medium maturity (50–79%): 4 modules
- 🔴 Low maturity (<50%): 0 modules
|
This pull request is automatically being deployed by Amplify Hosting (learn more). |
Why
I noticed we had
1024x1024logos in the repo and wondered why CI never caught them. The answer:ci/validate_modules.sh(run in CI via.pre-commit-config.yaml→pre-commit run --all-files) only ever ranpngquantand compared byte sizes. It never looked at pixel dimensions, so a large-but-already-well-quantized icon passed cleanly.Worst offender was
modules/aws/alternate-contacts/buildingblock/logo.pngat 2048x2048 / 2.0 MB.What changed
New
check_png_dimensionsalongside the existing minimization check:buildingblockPNGs larger than 512 px in either dimension.--fix.--fixresizes with Lanczos using512x512>— only ever shrinks, and preserves aspect ratio so non-square banners stay intact (600x315→512x269).--fixgets re-minimized in the same pass.Also fixed a silent-pass bug: if
pngquantwas missing, the old code hitelse rm -f "$temp_minimized"and quietly passed every PNG. It now reports an error.Icons resized / re-optimized
aws/alternate-contactsazuredevops/agent-poolske/ske-starterkitaks/postgresqlstackit/network-areastackit/networkstackit/storage-bucketazure/spoke-networkPlus optimization-only (already ≤512 px):
stackit/git-repository53054→47211 B,stackit/project2285→1878 B,stackit/stackit.png3594→1878 B.~2.3 MB removed overall. Every resized icon was rendered and compared side-by-side against its original — all visually unchanged.
Notes for reviewers
bash ci/validate_modules.shis green on this branch; onmainit reports the 8 dimension violations this PR fixes.max_png_dimensionat the top of the script..agents/skills/module/SKILL.mdstill recommends 256x256 for new logos — 512 is the hard ceiling, not the target.modules/*/*/buildingblockglob and are still oversized —kubernetes/logo.png(3600x3493, 504 KB),openshift/OpenShift-LogoType.png(1280x1056),sapbtp/sapbtp.png(1080x1080),ionos/LOGO_IONOS_Blue_RGB-1.png(1061x310),cloudfoundry/CloudFoundry.png(738x731). Widening the glob to cover them is a reasonable follow-up; kept out here to keep the diff reviewable.🤖 Generated with Claude Code