Skip to content

feat: add hadolint plugin for Containerfile linting#423

Merged
bschwedler merged 17 commits into
mainfrom
feature/hadolint-plugin
Apr 10, 2026
Merged

feat: add hadolint plugin for Containerfile linting#423
bschwedler merged 17 commits into
mainfrom
feature/hadolint-plugin

Conversation

@ianpittwood
Copy link
Copy Markdown
Contributor

Summary

  • Adds a new builtin hadolint plugin to posit-bakery that lints Containerfiles for each image target
  • Registers as bakery hadolint run CLI command with filter options and all hadolint configuration properties
  • Writes JSON results to results/hadolint/{image_name}/{uid}.json and displays a Rich summary table with detailed issue listings sectioned by image and UID
  • Provides HadolintOptions as a ToolOptions subclass for bakery.yaml configuration, surfacing all hadolint YAML config properties except format, verbose, and no-color
  • Default failure threshold is error; --verbose is set when bakery is in debug mode; NO_COLOR is inherited from the parent environment

Structure

posit_bakery/plugins/builtin/hadolint/
  __init__.py   # HadolintPlugin (BakeryToolPlugin implementation + CLI)
  options.py    # HadolintOptions (ToolOptions for bakery.yaml config)
  command.py    # HadolintCommand (builds hadolint CLI invocation)
  suite.py      # HadolintSuite (orchestrates execution across targets)
  report.py     # HadolintResult, HadolintReport, HadolintReportCollection
  errors.py     # BakeryHadolintError

Test plan

  • 46 new unit tests covering options, command building, report models, suite orchestration
  • All 1273 tests pass with no regressions
  • Integration test runs hadolint against real Containerfiles
  • Manual CLI testing with --failure-threshold error (default, warnings pass) and --failure-threshold warning (warnings fail)
  • Verbose mode (-v) correctly passes --verbose to hadolint
  • bakery.yaml hadolint options merge correctly with CLI overrides

🤖 Generated with Claude Code

@ianpittwood ianpittwood force-pushed the feature/hadolint-plugin branch from 8de4a40 to fb6d405 Compare April 3, 2026 20:32
@ianpittwood ianpittwood force-pushed the feature/oras-plugin branch 2 times, most recently from 0fddf2d to 1651b3e Compare April 7, 2026 18:21
@ianpittwood ianpittwood force-pushed the feature/hadolint-plugin branch from 74f8934 to 23a046a Compare April 7, 2026 21:01
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 7, 2026

Test Results

1 328 tests  +51   1 328 ✅ +51   8m 46s ⏱️ +22s
    1 suites ± 0       0 💤 ± 0 
    1 files   ± 0       0 ❌ ± 0 

Results for commit e5a532b. ± Comparison against base commit 291e13d.

♻️ This comment has been updated with latest results.

Base automatically changed from feature/oras-plugin to main April 7, 2026 21:14
@ianpittwood ianpittwood force-pushed the feature/hadolint-plugin branch from 23a046a to 4042655 Compare April 8, 2026 12:44
@ianpittwood ianpittwood marked this pull request as ready for review April 9, 2026 13:24
@ianpittwood ianpittwood requested a review from bschwedler as a code owner April 9, 2026 13:24
Comment thread setup-hadolint/action.yml Outdated
ianpittwood and others added 16 commits April 10, 2026 11:58
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds BakeryHadolintError (subclass of BakeryToolRuntimeError with parse_error
field and formatted stdout output) and HadolintSuite which runs hadolint
subprocesses per image target, writes JSON results to results/hadolint/, and
returns a (HadolintReportCollection, errors) tuple distinguishing parse failures
from lint findings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements the HadolintPlugin entry point with full CLI (bakery hadolint run),
execute(), and results() methods. Registers the plugin via pyproject.toml entry
point. Updates test_variant.py to reflect two default tool options (goss + hadolint).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d support

The execute() method was only checking report.error_count > 0 to determine
failure, ignoring the --failure-threshold flag. Now HadolintReport stores
the hadolint process exit code, which correctly reflects whether the
configured threshold was exceeded.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CLI --failure-threshold default no longer overrides bakery.yaml config;
  the "error" default is applied in HadolintCommand.from_image_target()
  only when no source provides a value
- Add errors/warnings properties to HadolintReport
- Add issues_by_level(threshold) to HadolintReportCollection
- Add tests for new properties and default threshold behavior

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The f-string `f"{self.message}'\n"` produced a trailing single-quote
after the error message in BakeryToolRuntimeError, BakeryDGossError,
and BakeryHadolintError.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Posit images do not pin OS-level package versions, so DL3008, DL3018,
DL3033, DL3037, and DL3041 are ignored by default. Users can override
with an explicit `ignored` list; setting `ignored: []` clears defaults.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Matrix versions sharing the same Containerfile are now linted only once.
The report uses "matrix" as the version label for deduplicated entries.
Issues are listed by Containerfile path instead of by image target, and
a Containerfile column is added to the summary table.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Passing None explicitly as a keyword argument to HadolintOptions caused
Pydantic to mark the field as set in model_fields_set, preventing the
default ignored rules from being applied. Only include CLI flags in the
constructor when they have non-None values.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Containerfiles with no lint issues are still shown in the summary table
but are now omitted from the detailed results section to reduce noise.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add hadolint to PATH for tests
@ianpittwood ianpittwood force-pushed the feature/hadolint-plugin branch from 470b093 to 8a06751 Compare April 10, 2026 17:58
Co-authored-by: Benjamin R. J. Schwedler <ben@posit.co>
@ianpittwood ianpittwood requested a review from bschwedler April 10, 2026 18:00
@bschwedler bschwedler enabled auto-merge April 10, 2026 18:03
@bschwedler bschwedler added this pull request to the merge queue Apr 10, 2026
Merged via the queue into main with commit 21bd1ab Apr 10, 2026
16 checks passed
@bschwedler bschwedler deleted the feature/hadolint-plugin branch April 10, 2026 18:21
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