Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 34 additions & 32 deletions hadolint/main.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
// A generated module for Hadolint functions
// A Dagger module to lint Dockerfiles using hadolint.
//
// This module has been generated via dagger init and serves as a reference to
// basic module structure as you get started with Dagger.
//
// Two functions have been pre-created. You can modify, delete, or add to them,
// as needed. They demonstrate usage of arguments and return types using simple
// echo and grep commands. The functions can be called from the dagger CLI or
// from one of the SDKs.
//
// The first line in this comment block is a short description line and the
// rest is a long description with more detail on the module's purpose or usage,
// if appropriate. All modules should have a short description.
// This module inspects Dockerfiles for best practices, security issues,
// and style violations using hadolint.
package main

import (
Expand All @@ -21,15 +12,15 @@ const (
defaultImageRepository = "hadolint/hadolint:latest-alpine"
)

// Hadolint is a module for checking Dockerfiles.
// Hadolint provides functions for linting Dockerfiles.
type Hadolint struct {
// +private
Image string
// +private
Ctr *dagger.Container
}

// New creates a new instance of the Hadolint struct
// New creates a new instance of the Hadolint struct.
func New(
// Custom image reference in "repository:tag" format to use as a base container.
// +optional
Expand All @@ -40,7 +31,7 @@ func New(
}
}

// Container returns the underlying Dagger container
// container returns the underlying Dagger container, lazily initialized.
func (m *Hadolint) container() *dagger.Container {
if m.Ctr != nil {
return m.Ctr
Expand All @@ -55,27 +46,38 @@ func (m *Hadolint) container() *dagger.Container {
return m.Ctr
}

// CheckWithConfig runs the hadolint-checker command with a configuration file.
func (m *Hadolint) CheckWithConfig(
// source is an optional argument that specifies a directory.
// Check runs hadolint on Dockerfiles found in the directory.
// It supports Dockerfile, Dockerfile.*, *.dockerfile, and Containerfile naming conventions.
func (m *Hadolint) Check(
// Source directory containing Dockerfiles.
source *dagger.Directory,
// file is an optional argument that specifies hadolint configuration file.
file *dagger.File,
// Optional hadolint configuration file (e.g. .hadolint.yaml).
// +optional
config *dagger.File,
) *dagger.Container {
return m.container().
WithMountedDirectory("/tmp", source).
WithWorkdir("/tmp").
WithFile("/.config/.hadolint.yaml", file).
WithExec([]string{"sh", "-c", "find . -type f \\( -name 'Dockerfile' -o -name 'Dockerfile.*' \\) -print0 | xargs -0 hadolint --config /.config/.hadolint.yaml"})
ctr := m.container().
WithMountedDirectory("/work", source).
WithWorkdir("/work")

configArg := ""
if config != nil {
ctr = ctr.WithFile("/etc/hadolint.yaml", config)
configArg = "--config /etc/hadolint.yaml "
}

// Finds all standard Dockerfile and Containerfile variants safely
cmd := "find . -type f \\( -name 'Dockerfile' -o -name 'Dockerfile.*' -o -name '*.dockerfile' -o -name 'Containerfile*' \\) -print0 | xargs -0 -r hadolint " + configArg

return ctr.WithExec([]string{"sh", "-c", cmd})
}

// Check runs the hadolint-checker command.
func (m *Hadolint) Check(
// source is an optional argument that specifies a directory.
// CheckWithConfig runs hadolint with a specific configuration file.
// Maintained for explicit backwards compatibility.
func (m *Hadolint) CheckWithConfig(
// Source directory containing Dockerfiles.
source *dagger.Directory,
// Configuration file for hadolint.
file *dagger.File,
) *dagger.Container {
return m.container().
WithMountedDirectory("/tmp", source).
WithWorkdir("/tmp").
WithExec([]string{"sh", "-c", "find . -type f \\( -name 'Dockerfile' -o -name 'Dockerfile.*' \\) -print0 | xargs -0 hadolint"})
return m.Check(source, file)
}
51 changes: 21 additions & 30 deletions hadolint/test/main.go
Original file line number Diff line number Diff line change
@@ -1,29 +1,18 @@
// A generated module for Hadolinttest functions
//
// This module has been generated via dagger init and serves as a reference to
// basic module structure as you get started with Dagger.
//
// Two functions have been pre-created. You can modify, delete, or add to them,
// as needed. They demonstrate usage of arguments and return types using simple
// echo and grep commands. The functions can be called from the dagger CLI or
// from one of the SDKs.
//
// The first line in this comment block is a short description line and the
// rest is a long description with more detail on the module's purpose or usage,
// if appropriate. All modules should have a short description.
// Package main provides tests for the Hadolint Dagger module.
package main

import (
"context"
"regexp"
"errors"
"strings"

"github.com/sourcegraph/conc/pool"
)

// Hadolinttest is a module for checking hadolint files.
// Hadolinttest provides test functions for the hadolint module.
type Hadolinttest struct{}

// All runs all tests.
// All runs all tests concurrently.
func (m *Hadolinttest) All(ctx context.Context) error {
p := pool.New().WithErrors().WithContext(ctx)

Expand All @@ -33,34 +22,36 @@ func (m *Hadolinttest) All(ctx context.Context) error {
return p.Wait()
}

// CheckWithConfig runs the hadolint-checker command with a configuration file.
// CheckWithConfig tests hadolint with an explicit configuration file.
func (m *Hadolinttest) CheckWithConfig(ctx context.Context) error {

dir := dag.CurrentModule().Source().Directory("./testdata")
file := dag.CurrentModule().Source().File("./testdata/.config/.hadolint.yaml")

_, err := dag.Hadolint().CheckWithConfig(dir, file).Stderr(ctx)
if err == nil {
return errors.New("expected hadolint to fail on invalid Dockerfile, but it succeeded")
}

if err != nil {
re := regexp.MustCompile("exit code: 123")
if re.MatchString(err.Error()) {
return nil
}
// xargs exits with 123 when the underlying linter fails
if strings.Contains(err.Error(), "exit code: 123") || strings.Contains(err.Error(), "exit code: 1") {
return nil
}

return err
}

// Check runs the hadolint-checker command.
// Check tests hadolint on invalid testdata without explicit configuration.
func (m *Hadolinttest) Check(ctx context.Context) error {

dir := dag.CurrentModule().Source().Directory("./testdata")

_, err := dag.Hadolint().Check(dir).Stderr(ctx)
if err == nil {
return errors.New("expected hadolint to fail on invalid Dockerfile, but it succeeded")
}

if err != nil {
re := regexp.MustCompile("exit code: 123")
if re.MatchString(err.Error()) {
return nil
}
// xargs exits with 123 when the underlying linter fails
if strings.Contains(err.Error(), "exit code: 123") || strings.Contains(err.Error(), "exit code: 1") {
return nil
}

return err
Expand Down
Loading