Skip to content

#58: add pinned Hadolint to lint checks - #66

Merged
deyna256 merged 2 commits into
deyna256:mainfrom
efegokdemir:58
Sep 20, 2026
Merged

deyna256 merged 2 commits into
deyna256:mainfrom
efegokdemir:58

Conversation

@efegokdemir

@efegokdemir efegokdemir commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Problem

The Dockerfile was not included in automated lint checks.

Changes

  • Run Hadolint 2.15.1 through a Docker image pinned by tag and digest.
  • Keep Go vet in the lint recipe.
  • Remove the standalone Hadolint installation from CI.
  • Document Docker as a requirement for linting.
  • Incorporate current upstream main.

This follows the maintainer's requested image-based approach.

Validation

  • Formatting: passed.

  • Dependency check: passed.

  • Go vet: passed.

  • Full test suite: passed.

  • Hadolint: Docker unavailable locally; Go vet passed. Hadolint requires GitHub CI verification.

Closes #58.

@deyna256 deyna256 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Summary: the check itself works, but it makes a local Hadolint install mandatory for every contributor while CONTRIBUTING only documents an unpinned macOS command, so please sort out the setup instructions (or the approach) before merge.

Blocking, inline: CONTRIBUTING.md:75 and CONTRIBUTING.md:83. The question on Justfile:15 is about the approach #58 proposed; answer it before deciding whether the documentation fix is enough.

Checked (at af0bc71):

  • Downloaded the pinned release: its SHA-256 matches the value in the workflow and hadolint --version prints Haskell Dockerfile Linter 2.15.1, so the case pattern matches and CI will pass.
  • just lint with that binary on PATH exits 0 on the current Dockerfile, and exits 1 with DL3006/DL3009 on a deliberately broken one, so #58's second requirement holds.
  • Without Hadolint on PATH just lint fails with the shell's hadolint: command not found followed by Hadolint 2.15.1 is required.; a 2.14.0 stub gives only the second message. Both exit 1.
  • brew currently ships 2.15.1, so the documented command works today; it is not pinned to it.
  • just format --check and just deps pass and change no files. No Go code changed.
  • The image hadolint/hadolint:v2.15.1@sha256:32dac94127fd60b7b7e3fbfc65e1383b9b5e25c9bfd7b8536de7a539fe68a12d prints the same version and produces byte-identical diagnostics and exit codes on both Dockerfiles.
  • I did not run the workflow itself; the install step is verified only by reproducing its commands locally.

Comment thread CONTRIBUTING.md Outdated
Use the commands in the [Justfile](Justfile): `just format` formats Go code,
`just format --check` checks formatting without changing files, `just deps` updates
and verifies dependencies, and `just lint` runs `go vet ./...`. `just test-unit`
and verifies dependencies, and `just lint` runs `go vet ./...` and Hadolint 2.15.1 on the Dockerfile. `just test-unit`

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Both added sentences are appended to existing paragraphs instead of being wrapped with them: this line is 118 characters and line 83 is 211, while the rest of the file sits around 80. The repository has a commit for exactly this (docs: rewrap the issue label paragraph), so please rewrap both paragraphs.

Comment thread CONTRIBUTING.md Outdated
analysis and test checks on pull requests to `main` and pushes to `main`.
Use the Go version in `go.mod` and the Just version pinned in the workflow.
Golangci-lint is not configured yet. `just build`, `just run`, `just down` and
Install Hadolint 2.15.1 locally (`brew install hadolint` on macOS). CI downloads the same release and verifies its SHA-256 checksum. Golangci-lint is not configured yet. `just build`, `just run`, `just down` and

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

just lint now fails outright without Hadolint, and this is the only setup guidance. Two gaps:

  • No Linux instructions, although CI runs ubuntu-24.04 and the Dockerfile work happens there. The workflow already has the exact commands (release URL plus sha256sum --check); pointing contributors at them would cost two lines.
  • brew install hadolint is not pinned. It gives 2.15.1 today, which I checked, so the instruction works now; the next upstream release turns the documented setup into a version this recipe rejects.

Please document an install that yields 2.15.1 on the platforms this project is developed on.

Comment thread Justfile Outdated
set -eu
go vet ./...
case "$(hadolint --version)" in
*" 2.15.1") ;;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Question: #58 proposed pinning the hadolint/hadolint image by tag and digest so that local runs and CI are the same, and this takes the other route: a local install that every contributor must provide, gated by a version string.

I ran the alternative to compare: docker run --rm -v "$PWD:/repo" -w /repo hadolint/hadolint:v2.15.1@sha256:32dac94127fd60b7b7e3fbfc65e1383b9b5e25c9bfd7b8536de7a539fe68a12d hadolint Dockerfile prints the same diagnostics with the same exit codes, needs no CI install step, and keeps the version in one place. The current shape spells 2.15.1 out in six places (twice here, twice in CONTRIBUTING, the step name and the release URL), and the checksum has to change with it.

Docker is already required for just build and just run, so it is not a new dependency. If you prefer the binary anyway, say why in the PR description so the deviation from the issue is on record.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Decision on the question above: please take the image route from #58.

# Run Go and Dockerfile static analysis without modifying files.
lint:
    go vet ./...
    docker run --rm -v "$PWD:/repo:ro" -w /repo \
      hadolint/hadolint:v2.15.1@sha256:32dac94127fd60b7b7e3fbfc65e1383b9b5e25c9bfd7b8536de7a539fe68a12d \
      hadolint Dockerfile

That removes the version gate, so the recipe goes back to a plain two-command recipe with no shebang, and the CI install step can go: just lint then runs the same bytes in CI as it does locally. I ran this exact command, including the read-only mount: exit 0 on the current Dockerfile, exit 1 with DL3006/DL3009 on a broken one, same diagnostics as the binary.

CONTRIBUTING then only needs to say that just lint also lints the Dockerfile with that pinned image and that Docker is required for it. That also closes the missing Linux instructions, since nothing has to be installed any more.

The cost we accept: about 0.45 s per just lint on a warm cache against 0.04 s for the binary, and a one-time 65 MB pull. Docker is already required for just build and just run.

@deyna256 deyna256 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Requesting changes again to record the decision: implement #58 with the pinned hadolint/hadolint image instead of a locally installed binary. Details and the exact command are in the Justfile thread.

This replaces the documentation ask on CONTRIBUTING.md:83 (nothing needs installing once the image is used), and leaves the rewrap on CONTRIBUTING.md:75 standing.

@efegokdemir

Copy link
Copy Markdown
Contributor Author

Addressed the review feedback by switching to the pinned Hadolint Docker image, updating the documentation, and removing the separate CI installation. The quality check is passing. Ready for re-review.

@deyna256 deyna256 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Summary: this is the shape #58 asked for, the version now lives in one place, and it works the same locally and in CI. One documentation line was missed, so requesting changes for that alone.

Blocking:

  • docs/development.md:241 still reads ``just lintrunsgo vet ./...`.` That sentence is where the tooling section says what the command does, and from this merge on it describes half of it while CONTRIBUTING describes all of it. Extend it the way CONTRIBUTING is extended, or drop the enumeration there and leave the rule above it, "Pin tool versions and use the same versions locally and in CI", which this change now satisfies.

Non-blocking:

  • Justfile:12 the mount is wider than the job needs. Details inline; it came from my own snippet.

Checked: worktree at 3d57196, Docker 29.8.1.

  • just lint exits 0 on the current Dockerfile: 14.6 s cold including the image pull, 0.46 s warm. On a Dockerfile with FROM golang and an unpinned apt-get install it exits 1 with DL3006, DL3008, DL3015 and DL3009, and just names the failing recipe line.
  • Run from internal/codex, the recipe still lints the repository's Dockerfile, so $PWD follows just's working directory and not the caller's.
  • The pin resolves as intended: sha256:32dac941… is the index digest of hadolint/hadolint:v2.15.1, and that index carries linux/amd64 and linux/arm64, so the pin is not architecture-specific. hadolint --version inside it prints 2.15.1.
  • The CI log for this head shows the pinned image pulled and run inside just lint, the whole static analysis step taking 4 s, with no install step left in the workflow. Local and CI now run the same bytes.
  • just format --check, just deps --check and just test pass. CI quality is green and the branch is mergeable.
  • The new CONTRIBUTING lines wrap at 69 to 78 characters, in line with the rest of the file, so the earlier wrapping nit is closed.

@deyna256
deyna256 dismissed their stale review September 20, 2026 10:42

Dismissed: the documentation line and the mount nit are ours to land in main, nothing left for the author here.

@deyna256 deyna256 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

lgtm, thanks!

Checked out 3d57196: just lint exits 0 on the current Dockerfile and 1 with DL3006/DL3008/DL3015/DL3009 on a broken one, 0.46 s warm, and it lints the right file when run from a subdirectory. The pin is the index digest of hadolint/hadolint:v2.15.1, covering linux/amd64 and linux/arm64, and the CI log shows that same image pulled and run inside just lint with no install step left in the workflow.

Two small leftovers are mine to land in main after this merges, nothing for you to do here.

@deyna256
deyna256 merged commit 5276b33 into deyna256:main Sep 20, 2026
1 check passed
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.

Lint the Dockerfile with hadolint in CI and just

2 participants