Skip to content

[OPIK-6673] [CI] feat: add hadolint Dockerfile linting to CI#7352

Open
JetoPistola wants to merge 3 commits into
mainfrom
danield/OPIK-6673-add-hadolint-dockerfile-linting-to-ci
Open

[OPIK-6673] [CI] feat: add hadolint Dockerfile linting to CI#7352
JetoPistola wants to merge 3 commits into
mainfrom
danield/OPIK-6673-add-hadolint-dockerfile-linting-to-ci

Conversation

@JetoPistola

@JetoPistola JetoPistola commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Details

image

Adds hadolint Dockerfile linting to the unified 🐙 Code Quality pipeline, so every Dockerfile is linted on each PR (changed-files-only) and new violations fail the check with inline annotations.

Rather than a standalone workflow (as the ticket's original HOW note suggested — written before the CI consolidation in #7165), hadolint is added as a hook in the root .pre-commit-config.yaml, the single source of truth. It flows automatically into code_quality.yml via the existing per-linter matrix detector, and is also runnable locally via make precommit.

  • .pre-commit-config.yamlhadolint-docker hook (pinned v2.14.0, runs via the hadolint Docker image so no local binary is needed, matching CI runners). Uses an explicit files: regex instead of the upstream types: [dockerfile] so scripts/precommit-detect-hooks.py (which matches on paths) routes changed Dockerfiles to it.

  • No .hadolint.yaml — hadolint's default rule set (failure threshold info) is used as-is. No repo-level config file: there are no global ignores (the deliberate exceptions are inline in the Dockerfiles) and no custom overrides, so a config file would only restate the default. (Minor divergence from the ticket's AC, which listed "a .hadolint.yaml exists": that AC assumed exceptions would be baselined in the config. We fixed the violations and put the few exceptions inline instead, so an empty config would add nothing — it can be re-added the moment an override or threshold change is actually needed.)

  • All pre-existing violations fixed across the 4 non-clean Dockerfiles. The only suppressions left are the three OS-package pinning rules that would rot against rolling-channel base-image repos (DL3033 yum / DL3008 apt / DL3018 apk), each ignored per-line with a reason, not globally — so the rules still fire on any new Dockerfile. Everything else is a genuine fix: consecutive-RUN merges (DL3059), pipefail SHELL (DL4006; /bin/ash for the alpine python-backend), find -print0 | xargs -0 (SC2038), and pip floated from a >=24 floor rather than ignoring DL3013.

    On OS-package pinning specifically: exact-pinning distro packages (apt-get install curl=7.88.1-10) is a known anti-pattern — distro mirrors are rolling and drop old versions on the next security update, so a pinned build breaks on a later rebuild. The robust reproducibility lever is base-image digest pinning (FROM ubuntu:22.04@sha256:…) plus scheduled rebuilds + the existing vulnerability scan — a separate concern worth its own change. Hence the per-line ignores here.

Change checklist

  • CI/tooling change
  • Existing Dockerfiles updated to pass the new lint gate
  • Documentation updated (CONTRIBUTING.md)

Issues

Resolves OPIK-6673

Testing

  • hadolint exits 0 on all 5 Dockerfiles (backend, frontend, guardrails, python-backend, sandbox-executor).
  • Ran the hook via pre-commit run hadolint-docker — passes on the clean files, and fails with inline annotations on a fresh violation (verified with a throwaway FROM ubuntu:latest + unpinned apt-get install).
  • scripts/precommit-detect-hooks.py verified both ways: a changed Dockerfile emits a hadolint leg; a non-Dockerfile change does not.
  • Built the opik-frontend builder stage locally after the DL3059 RUN-merge and confirmed dist/version.json is still produced correctly.
  • The guardrails, python-backend, and backend Dockerfile edits are built + booted + E2E-tested on this PR by guardrails_e2e_tests.yml and python_backend_e2e_tests.yml (both path-triggered on the dirs this PR touches).

Documentation

Added a "Dockerfiles" section to CONTRIBUTING.md explaining the hadolint gate and how to run it locally.

🤖 Generated with Claude Code

Add hadolint to the unified Code Quality pipeline so every Dockerfile is
linted on each PR (changed-files-only) via the existing pre-commit-driven
matrix in code_quality.yml. New violations on changed Dockerfiles fail the
check with inline annotations.

- .pre-commit-config.yaml: hadolint-docker hook (Docker image, no local
  binary), explicit files: regex so the CI matrix detector routes changed
  Dockerfiles to it.
- .hadolint.yaml: default rule set, failure-threshold info, no global
  ignores; the four version-pinning rules that would rot against
  rolling-channel base-image repos are suppressed per-line with a reason.
- Fix all pre-existing violations across the 4 non-clean Dockerfiles:
  merge consecutive RUNs (DL3059), add pipefail SHELL (DL4006; /bin/ash
  for the alpine python-backend), find -print0 | xargs -0 (SC2038).
- CONTRIBUTING.md: how to run hadolint locally.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

⏱️ pre-commit per-hook timing

Hook Description Result Duration
🐳 hadolint — dockerfiles Lint Dockerfiles 2.75s
🛡️ fix end of files — guardrails Ensure files end in a newline 0.03s
🛡️ trim trailing whitespace — guardrails Strip trailing whitespace 0.03s
Total (3 ran) 2.81s
⏭️ 38 skipped (no matching files changed)
Hook Description Result
🐍 trim trailing whitespace — python sdk Strip trailing whitespace ⏭️
🐍 fix end of files — python sdk Ensure files end in a newline ⏭️
🐍 ruff — python sdk Lint + autofix Python (ruff) ⏭️
🐍 ruff-format — python sdk Format Python code (ruff) ⏭️
🐍 mypy — python sdk Static type check ⏭️
🤖 trim trailing whitespace — optimizer Strip trailing whitespace ⏭️
🤖 fix end of files — optimizer Ensure files end in a newline ⏭️
🤖 check yaml — optimizer Validate YAML syntax ⏭️
🤖 check json — optimizer Validate JSON syntax ⏭️
🤖 check toml — optimizer Validate TOML syntax ⏭️
🤖 check for added large files — optimizer Block large files (>1MB) ⏭️
🔐 detect private key — optimizer Block committed private keys ⏭️
🤖 check for merge conflicts — optimizer Block merge-conflict markers ⏭️
🤖 check for case conflicts — optimizer Block case-only name clashes ⏭️
🤖 pyupgrade — optimizer Modernize Python syntax ⏭️
🤖 ruff — optimizer Lint + autofix Python (ruff) ⏭️
🤖 ruff-format — optimizer Format Python code (ruff) ⏭️
🤖 mypy — optimizer Static type check ⏭️
📓 nbstripout — optimizer notebooks Strip notebook output ⏭️
📝 markdownlint — optimizer Lint Markdown ⏭️
🔤 codespell — optimizer Fix common misspellings ⏭️
📊 radon cc — optimizer Cyclomatic-complexity gate ⏭️
📊 radon raw — optimizer Raw size metrics gate ⏭️
📊 xenon — optimizer Fail on complexity thresholds ⏭️
📊 lizard — optimizer Cyclomatic-complexity gate ⏭️
🧹 vulture — optimizer Find dead code ⏭️
🛡️ ruff — guardrails Lint + autofix Python (ruff) ⏭️
🛡️ ruff-format — guardrails Format Python code (ruff) ⏭️
🛡️ mypy — guardrails Static type check ⏭️
⚓ helm-docs Regenerate Helm chart README ⏭️
block non-public FE plugins Block non-public FE plugins ⏭️
☕ spotless — java backend Format Java code ⏭️
🧪 pre-commit wrapper smoke tests Self-test the wrapper scripts ⏭️
🌐 eslint — frontend Lint + autofix JS/TS ⏭️
🌐 typecheck — frontend Whole-project tsc type check ⏭️
📘 eslint — typescript sdk Lint + autofix JS/TS ⏭️
📘 typecheck — typescript sdk Whole-project tsc type check ⏭️
⚙️ actionlint — github workflows Lint GitHub Actions workflows ⏭️

…f ignoring DL3013

- scripts/precommit-hook-descriptions.tsv: add hadolint → "Lint Dockerfiles"
  so the Code Quality timing/skipped tables render a description for it.
- guardrails Dockerfile: replace the DL3013 ignore with a real fix — float pip
  from a >=24 floor (Ubuntu 22.04 ships pip ~22, too old for the pinned
  torch/transformers/hf_xet wheels). A lower bound doesn't rot, and it satisfies
  DL3013 honestly. Remaining suppressions are only the rolling-channel OS-package
  pin rules (DL3008/DL3018/DL3033).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@JetoPistola JetoPistola added the test-environment Deploy Opik adhoc environment label Jul 6, 2026
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

🔄 Test environment deployment process has started

Phase 1: Deploying base version 2.1.16-5907 (from main branch) if environment doesn't exist
Phase 2: Building new images from PR branch danield/OPIK-6673-add-hadolint-dockerfile-linting-to-ci
Phase 3: Will deploy newly built version after build completes

You can monitor the progress here.

@CometActions

Copy link
Copy Markdown
Collaborator

Test environment is now available!

To configure additional Environment variables for your environment, run [Deploy Opik AdHoc Environment workflow] (https://github.com/comet-ml/comet-deployment/actions/workflows/deploy_opik_adhoc_env.yaml)

Access Information

The deployment has completed successfully and the version has been verified.

…verrides

The config only restated hadolint's default failure-threshold (info) and held
no global ignores (the deliberate exceptions are inline `# hadolint ignore=`
comments in the Dockerfiles). With nothing repo-specific to configure, the file
was pure overhead. Removing it keeps identical behavior — hadolint falls back to
its info default — and drops a file reviewers would otherwise have to reason about.
Docs updated to match.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@CometActions

Copy link
Copy Markdown
Collaborator

🌙 Nightly cleanup: The test environment for this PR (pr-7352) has been cleaned up to free cluster resources. PVCs are preserved — re-deploy to restore the environment.

@CometActions CometActions removed the test-environment Deploy Opik adhoc environment label Jul 6, 2026
@JetoPistola JetoPistola added the test-environment Deploy Opik adhoc environment label Jul 6, 2026
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

🔄 Test environment deployment process has started

Phase 1: Deploying base version 2.1.16-5907 (from main branch) if environment doesn't exist
Phase 2: Building new images from PR branch danield/OPIK-6673-add-hadolint-dockerfile-linting-to-ci
Phase 3: Will deploy newly built version after build completes

You can monitor the progress here.

@CometActions

Copy link
Copy Markdown
Collaborator

Test environment is now available!

To configure additional Environment variables for your environment, run [Deploy Opik AdHoc Environment workflow] (https://github.com/comet-ml/comet-deployment/actions/workflows/deploy_opik_adhoc_env.yaml)

Access Information

The deployment has completed successfully and the version has been verified.

@JetoPistola JetoPistola marked this pull request as ready for review July 6, 2026 07:26
@JetoPistola JetoPistola requested review from a team as code owners July 6, 2026 07:26
@CometActions

Copy link
Copy Markdown
Collaborator

🌙 Nightly cleanup: The test environment for this PR (pr-7352) has been cleaned up to free cluster resources. PVCs are preserved — re-deploy to restore the environment.

@CometActions CometActions removed the test-environment Deploy Opik adhoc environment label Jul 7, 2026
@JetoPistola JetoPistola added the test-environment Deploy Opik adhoc environment label Jul 7, 2026
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

🔄 Test environment deployment process has started

Phase 1: Deploying base version 2.1.16-5907 (from main branch) if environment doesn't exist
Phase 2: Building new images from PR branch danield/OPIK-6673-add-hadolint-dockerfile-linting-to-ci
Phase 3: Will deploy newly built version after build completes

You can monitor the progress here.

@CometActions

Copy link
Copy Markdown
Collaborator

Test environment is now available!

To configure additional Environment variables for your environment, run [Deploy Opik AdHoc Environment workflow] (https://github.com/comet-ml/comet-deployment/actions/workflows/deploy_opik_adhoc_env.yaml)

Access Information

The deployment has completed successfully and the version has been verified.

@CometActions

Copy link
Copy Markdown
Collaborator

🌙 Nightly cleanup: The test environment for this PR (pr-7352) has been cleaned up to free cluster resources. PVCs are preserved — re-deploy to restore the environment.

@CometActions CometActions removed the test-environment Deploy Opik adhoc environment label Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants