Skip to content

Fix Docker image tags to be lowercase for GHCR - #25

Merged
jantman merged 1 commit into
mainfrom
fix-release-lowercase-image
Jun 13, 2026
Merged

Fix Docker image tags to be lowercase for GHCR#25
jantman merged 1 commit into
mainfrom
fix-release-lowercase-image

Conversation

@jantman

@jantman jantman commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Problem

The v0.5.0 Release build (on the merge of #24) failed:

ERROR: failed to build: invalid tag "ghcr.io/DecaturMakers/kiosk-show-replacement:0.5.0": repository name must be lowercase

GHCR and the Docker tag spec require repository names to be entirely lowercase. The workflows tag images as ghcr.io/${{ github.repository }}:..., and ${{ github.repository }} preserves the owner's casing — DecaturMakers/kiosk-show-replacement. This was fine under the old all-lowercase jantman owner but breaks under the mixed-case org.

Fix

Add a Compute lowercase image name step to both the Release and CI Docker-build jobs that lowercases $GITHUB_REPOSITORY with bash ${VAR,,} expansion, and reference its output (steps.image.outputs.name) for:

  • the release version / latest image tags
  • the CI ci-<sha> image tag
  • the docker pull commands in the release-notes body

OCI labels and GitHub URLs keep ${{ github.repository }} — they're case-insensitive and not subject to the tag constraint.

Effect

The failed run errored before the "Create GitHub Release" step, so no v0.5.0 tag/release exists yet. Once this merges to main, the Release workflow re-triggers (pyproject 0.5.0 > latest release 0.4.0) and should publish the v0.5.0 image and GitHub release.

🤖 Generated with Claude Code

The v0.5.0 release build failed with:

  invalid tag "ghcr.io/DecaturMakers/kiosk-show-replacement:0.5.0":
  repository name must be lowercase

GHCR (and the Docker tag spec) require repository names to be all
lowercase, but ${{ github.repository }} preserves the owner's casing.
This worked under the previous all-lowercase "jantman" owner and broke
once the repo moved to the mixed-case "DecaturMakers" organization.

Add a "Compute lowercase image name" step to both the release and CI
Docker build jobs that lowercases $GITHUB_REPOSITORY via bash ${VAR,,}
expansion, and reference its output for all ghcr.io image tags
(release version/latest tags, the CI ci-<sha> tag) and the docker pull
commands in the release notes body.

OCI image labels and GitHub URLs are left using ${{ github.repository }}
since those are case-insensitive and not subject to the tag constraint.

Once merged, the release workflow will re-run (0.5.0 > the 0.4.0 latest
release) and publish the v0.5.0 image and GitHub release.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 13, 2026 13:43

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes GHCR/Docker tag generation in the CI and Release workflows by ensuring the image repository name is always lowercase (required by GHCR), avoiding failures when the GitHub org name contains uppercase characters.

Changes:

  • Add a “Compute lowercase image name” step that lowercases $GITHUB_REPOSITORY and exposes it as steps.image.outputs.name.
  • Update Docker build/push tags to use the computed lowercase image name in both Release and CI.
  • Update the Release notes’ docker pull commands to use the computed lowercase image name.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
.github/workflows/release.yml Computes a lowercase GHCR image name and uses it for release tags and release-notes pull commands.
.github/workflows/ci.yml Computes a lowercase GHCR image name and uses it for CI image tagging.

@github-actions

Copy link
Copy Markdown

Coverage

Coverage Report
FileStmtsMissCoverMissing
__init__.py100100% 
app.py1383177%35, 75, 193, 235–236, 238–239, 241–244, 256–258, 261, 263, 273, 275, 278–279, 282–285, 289–292, 295–296, 299
database_utils.py17013023%30–36, 41–47, 57, 59–61, 64–65, 67–69, 72–74, 77, 79, 88, 90–93, 95, 116, 118, 121–123, 126, 129, 131–132, 134–135, 137–139, 142–146, 159, 161–164, 167, 177, 186–187, 190, 219, 247, 250, 283–284, 286–287, 289–292, 301, 303, 308, 310, 315, 318–319, 324, 326, 333, 336–337, 339–340, 347–348, 356, 361, 384–387, 390, 393–396, 399–401, 404–406, 408–409, 411–413, 426–429, 431–433, 436, 439, 442, 445–447, 449–450, 452–454
db_resilience.py122397%186, 256, 280
exceptions.py1100100% 
health.py1121685%81–83, 86–87, 98, 119–120, 134, 147, 158–160, 170–172
ical_parser.py113694%85, 120, 124, 127, 134, 197
ical_service.py1701889%80, 82–85, 87, 127–128, 130, 233, 342, 368–369, 375, 382, 454, 456, 460
logging_config.py81396%110, 112, 190
metrics.py236697%426–427, 471–472, 482–483
middleware.py36683%77, 95–96, 109–110, 117
migration_utils.py73730%8–9, 11–12, 15, 18–19, 26–32, 34–35, 46–48, 50–55, 57–58, 68–70, 72–77, 79–80, 90–96, 98–99, 105–108, 110–111, 117–120, 122–123, 133–138, 141, 144, 151, 153–154, 156, 161–162
sse.py1675865%45, 47–48, 50–51, 53–54, 57–59, 61–62, 65–66, 68, 118, 120–122, 204, 210–211, 213–214, 218, 225, 227–228, 230, 232, 234, 309, 322, 324, 332, 335–336, 338, 341, 345–346, 348, 352–353, 355, 358–359, 361, 365, 369–370, 372, 383, 395–398, 449
storage.py3314985%88–90, 156–157, 163, 168, 259–261, 489–491, 512, 526, 573–576, 580, 604–606, 617–619, 675–676, 680, 701–703, 743–746, 774–775, 777–783, 785, 832–833, 860
storage_resilience.py1635367%68–69, 203–204, 211, 213–219, 266–270, 303–305, 334, 347–348, 352–358, 362–364, 382, 384–389, 391–401, 403, 405
validation.py1381787%221, 223, 229, 263, 265–266, 268–269, 337–342, 348, 376, 413
api
   __init__.py10280%27, 38
   helpers.py772074%170, 179, 222, 230, 235, 243, 248, 256, 261, 270, 275, 283–286, 293, 301–304
   v1.py157664559%89, 177–179, 219, 225, 231, 240, 262, 290–292, 304, 341, 345, 361–364, 455, 488, 492, 495, 515–516, 519, 529, 533, 537, 656–658, 661, 675, 679, 683, 687, 752, 755–756, 761–762, 765–766, 768–769, 772–773, 776, 789, 800, 823–826, 842, 846, 850, 876–879, 889, 893, 897, 901, 905, 926, 933–935, 952–957, 975, 979, 998–1002, 1025, 1040–1042, 1057, 1064–1066, 1080, 1089–1091, 1108, 1119–1121, 1131, 1135, 1140, 1145, 1150, 1170–1171, 1187–1190, 1200, 1204, 1208–1210, 1220, 1224, 1228, 1244–1245, 1249, 1262, 1319–1322, 1329–1332, 1334–1336, 1338–1340, 1343–1344, 1347–1350, 1353–1354, 1357, 1365–1366, 1368, 1371, 1382, 1387, 1390, 1394–1398, 1401, 1411, 1415, 1426–1429, 1441–1444, 1446–1448, 1450–1451, 1453–1454, 1456, 1459, 1461–1464, 1471–1474, 1476–1478, 1480–1481, 1483–1485, 1487, 1490, 1492–1495, 1512, 1540–1542, 1549–1551, 1553, 1555–1557, 1576, 1578–1581, 1584, 1587–1592, 1595, 1598, 1600, 1602–1606, 1618–1621, 1623, 1626, 1628, 1630–1632, 1639–1642, 1644–1646, 1649–1650, 1653, 1656–1657, 1660, 1673–1674, 1676, 1679, 1683–1693, 1700–1703, 1705–1707, 1709–1710, 1712, 1714–1716, 1723–1726, 1728–1730, 1732–1733, 1735–1737, 1740, 1742, 1749–1751, 1753–1766, 1768–1769, 1771, 1774, 1776–1786, 1793–1796, 1798–1800, 1802–1803, 1805–1807, 1809, 1812, 1814–1817, 1828–1831, 1833–1835, 1837–1839, 1841–1842, 1844–1845, 1848–1850, 1852, 1855, 1857–1862, 1865, 1872–1875, 1877–1879, 1881–1882, 1884–1887, 1889–1891, 1893–1894, 1897–1899, 1901–1905, 1908, 1910–1911, 1914, 1916–1917, 1919–1920, 1922, 1924, 1928, 1935, 1939–1942, 1984, 2064–2066, 2069–2070, 2078, 2084, 2092, 2101, 2122, 2126, 2156–2158, 2160–2162, 2170, 2180, 2184, 2223–2225, 2227–2229, 2237, 2264, 2272, 2316–2318, 2320–2322, 2324–2326, 2330, 2357, 2377, 2387, 2405–2407, 2409–2411, 2419, 2457–2459, 2467, 2482, 2490, 2514, 2522, 2534–2536, 2546, 2550, 2554, 2559, 2564–2565, 2570, 2586, 2598–2600, 2642, 2650, 2677–2679, 2689, 2700–2701, 2709–2711, 2736, 2738, 2741, 2745, 2747, 2749–2754, 2760, 2762–2764, 2767, 2772–2773, 2775, 2779, 2781–2783, 2799, 2801, 2803, 2807, 2813–2814, 2816–2822, 2825–2826, 2829–2837, 2840–2848, 2850–2851, 2854–2855, 2858–2859, 2862–2868, 2872, 2874, 2876–2877, 2880, 2896, 2950–2952, 2959–2960, 2962–2964, 2966–2968, 2971, 2980, 2982, 2986, 2996–2998, 3021, 3050–3052, 3172–3173, 3180–3181, 3183–3185, 3187–3189, 3191, 3194, 3197, 3200–3202, 3204–3211, 3213–3214, 3216–3221, 3223, 3226–3227, 3229–3230, 3243, 3246–3247, 3251, 3253–3254, 3266–3267, 3271, 3275, 3286–3288, 3291
auth
   __init__.py40100% 
   decorators.py481275%54, 106, 122, 132–134, 136, 148–149, 151, 153–154
   views.py831878%73, 75–77, 120–121, 162–163, 165–166, 172, 240–241, 244–245, 254, 258, 267
cli
   __init__.py10100% 
   init_db.py856721%41–46, 48–49, 52–55, 57–58, 61–62, 65–66, 68, 73, 75–79, 81–82, 85–92, 94, 96, 100, 102–103, 141–142, 145, 148–151, 153–157, 159, 162, 171–173, 176–177, 179–183, 185, 187–188
   main.py351557%17, 28, 30–32, 41, 43–44, 53–54, 56, 58–59, 61, 66
config
   __init__.py580100% 
dashboard
   __init__.py20100% 
   views.py561769%88–91, 151, 153–157, 159, 161, 163, 165, 177, 188–189
display
   __init__.py20100% 
   views.py1514768%31, 33, 38, 53, 171–172, 187, 195, 230–231, 239, 273, 275–276, 278, 280–281, 283, 285, 306–308, 311–312, 314, 325, 333–334, 343, 354, 356–357, 364, 366, 368, 375, 388, 391, 410, 413, 415–416, 423, 425, 427, 433, 444
main
   __init__.py17170%10, 12, 14, 17, 20–21, 30, 33–35, 42, 45, 52, 55–56, 63, 69
models
   __init__.py4794391%126, 141, 263, 405, 407, 414, 431, 559, 584, 592, 594, 601, 609, 617, 725, 792, 799, 827, 885, 890, 924–927, 930, 1096, 1112, 1115, 1117, 1165–1166, 1168–1173, 1179, 1181, 1200, 1203, 1210, 1213
slideshow
   __init__.py503432%43, 46, 52–54, 56–58, 61–64, 66, 73–77, 80–82, 84, 90–91, 97, 103, 105, 107–112, 114
static
   __init__.py00100% 
templates
   __init__.py00100% 
utils
   __init__.py523532%43–46, 49–52, 65, 67–69, 71–72, 75–79, 92–97, 110–111, 121, 135–137, 140, 143–144, 146
TOTAL4956144170% 

Tests Skipped Failures Errors Time
687 1 💤 0 ❌ 0 🔥 59.264s ⏱️

@jantman
jantman merged commit b680353 into main Jun 13, 2026
8 checks passed
@jantman
jantman deleted the fix-release-lowercase-image branch June 13, 2026 13:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants