Skip to content

Commit

Permalink
lint: generate _index.md docs
Browse files Browse the repository at this point in the history
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
  • Loading branch information
crazy-max committed Jun 6, 2024
1 parent 811b2eb commit fb6a825
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 61 deletions.
127 changes: 70 additions & 57 deletions frontend/dockerfile/docs/rules/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,60 +20,73 @@ the rules. To run a check, use the `--check` flag:
$ docker build --check .
```

The available rules for build checks are:

- [`DuplicateStageName`](./duplicate-stage-name.md)

Stage names should be unique.

- [`FileConsistentCommandCasing`](./file-consistent-command-casing.md)

All commands within the Dockerfile should use the same casing (either uppercase or lowercase).

- [`FromAsCasing`](./from-as-casing.md)

The `AS` keyword should match the case of the `FROM` keyword.

- [`JSONArgsRecommended`](./json-args-recommended.md)

JSON arguments recommended for `ENTRYPOINTCMD` and `CMD` to prevent unintended behavior related to OS signals.

- [`MaintainerDeprecated`](./maintainer-deprecated.md)

The maintainer instruction is deprecated, use a label to define an image author instead.

- [`MultipleInstructionsDisallowed`](./multiple-instructions-disallowed.md)

Multiple instructions of the same type should not be used in the same stage.

- [`NoEmptyContinuations`](./no-empty-continuations.md)

Empty continuation lines will become errors in a future release.

- [`ReservedStageName`](./reserved-stage-name.md)

Reserved stage names should not be used to name a stage.

- [`SelfConsistentCommandCasing`](./self-consistent-command-casing.md)

Commands should be in consistent casing (all lowercase or all uppercase).

- [`StageNameCasing`](./stage-name-casing.md)

Stage names should be lowercase.

- [`UndeclaredArgInFrom`](./undeclared-arg-in-from.md)

`FROM` command must use declared `ARG` instructions.

- [`UndefinedArg`](./undefined-arg.md)

`ARG` should be defined before their use.

- [`UndefinedVar`](./undefined-var.md)

Variables should be defined before their use.

- [`WorkdirRelativePath`](./workdir-relative-path.md)

Using `WORKDIR` with relative paths without an absolute `WORKDIR` declared within the build can have unexpected results if the base image changes.
<table>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="./stage-name-casing.md">StageNameCasing</a></td>
<td>Stage names should be lowercase</td>
</tr>
<tr>
<td><a href="./from-as-casing.md">FromAsCasing</a></td>
<td>The 'as' keyword should match the case of the 'from' keyword</td>
</tr>
<tr>
<td><a href="./no-empty-continuations.md">NoEmptyContinuations</a></td>
<td>Empty continuation lines will become errors in a future release</td>
</tr>
<tr>
<td><a href="./self-consistent-command-casing.md">SelfConsistentCommandCasing</a></td>
<td>Commands should be in consistent casing (all lower or all upper)</td>
</tr>
<tr>
<td><a href="./file-consistent-command-casing.md">FileConsistentCommandCasing</a></td>
<td>All commands within the Dockerfile should use the same casing (either upper or lower)</td>
</tr>
<tr>
<td><a href="./duplicate-stage-name.md">DuplicateStageName</a></td>
<td>Stage names should be unique</td>
</tr>
<tr>
<td><a href="./reserved-stage-name.md">ReservedStageName</a></td>
<td>Reserved stage names should not be used to name a stage</td>
</tr>
<tr>
<td><a href="./jsonargs-recommended.md">JSONArgsRecommended</a></td>
<td>JSON arguments recommended for ENTRYPOINT/CMD to prevent unintended behavior related to OS signals</td>
</tr>
<tr>
<td><a href="./maintainer-deprecated.md">MaintainerDeprecated</a></td>
<td>The maintainer instruction is deprecated, use a label instead to define an image author</td>
</tr>
<tr>
<td><a href="./undeclared-arg-in-from.md">UndeclaredArgInFrom</a></td>
<td>FROM command must use declared ARGs</td>
</tr>
<tr>
<td><a href="./workdir-relative-path.md">WorkdirRelativePath</a></td>
<td>Relative workdir without an absolute workdir declared within the build can have unexpected results if the base image changes</td>
</tr>
<tr>
<td><a href="./undefined-var.md">UndefinedVar</a></td>
<td>Variables should be defined before their use</td>
</tr>
<tr>
<td><a href="./multiple-instructions-disallowed.md">MultipleInstructionsDisallowed</a></td>
<td>Multiple instructions of the same type should not be used in the same stage</td>
</tr>
<tr>
<td><a href="./legacy-key-value-format.md">LegacyKeyValueFormat</a></td>
<td>Legacy key/value format with whitespace separator should not be used</td>
</tr>
<tr>
<td><a href="./invalid-base-image-platform.md">InvalidBaseImagePlatform</a></td>
<td>Base image platform does not match expected target platform</td>
</tr>
</tbody>
</table>
38 changes: 38 additions & 0 deletions frontend/dockerfile/linter/docs/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: Build checks
description: |
BuildKit has built-in support for analyzing your build configuration based on
a set of pre-defined rules for enforcing Dockerfile and building best
practices.
keywords: buildkit, linting, dockerfile, frontend, rules
---

BuildKit has built-in support for analyzing your build configuration based on a
set of pre-defined rules for enforcing Dockerfile and building best practices.
Adhering to these rules helps avoid errors and ensures good readability of your
Dockerfile.

Checks run as a build invocation, but instead of producing a build output, it
performs a series of checks to validate that your build doesn't violate any of
the rules. To run a check, use the `--check` flag:

```console
$ docker build --check .
```

<table>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{{- range .Rules }}
<tr>
<td><a href="./{{.Filename}}">{{.Name}}</a></td>
<td>{{.Description}}</td>
</tr>
{{- end }}
</tbody>
</table>
36 changes: 32 additions & 4 deletions frontend/dockerfile/linter/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
type Rule struct {
Name string
Description string
Filename string
}

const tmplStr = `---
Expand Down Expand Up @@ -52,18 +53,20 @@ func run(destDir string) error {
if err != nil {
return err
}
tmpl, err := template.New("rule").Parse(tmplStr)

tmplRule, err := template.New("rule").Parse(tmplStr)
if err != nil {
return err
}
for _, rule := range rules {
if ok, err := genRuleDoc(rule, tmpl); err != nil {
if ok, err := genRuleDoc(rule, tmplRule); err != nil {
return errors.Wrapf(err, "Error generating docs for %s", rule.Name)
} else if ok {
log.Printf("Docs generated for %s\n", rule.Name)
}
}
return nil

return genIndex(rules)
}

func genRuleDoc(rule Rule, tmpl *template.Template) (bool, error) {
Expand All @@ -72,7 +75,7 @@ func genRuleDoc(rule Rule, tmpl *template.Template) (bool, error) {
if err != nil {
return false, err
}
outputfile, err := os.Create(path.Join(destDir, fmt.Sprintf("%s.md", camelToKebab(rule.Name))))
outputfile, err := os.Create(path.Join(destDir, rule.Filename))
if err != nil {
return false, err
}
Expand All @@ -89,6 +92,30 @@ func genRuleDoc(rule Rule, tmpl *template.Template) (bool, error) {
return true, nil
}

func genIndex(rules []Rule) error {
content, err := os.ReadFile("docs/_index.md")
if err != nil {
return err
}

tmpl, err := template.New("index").Parse(string(content))
if err != nil {
return err
}

outputfile, err := os.Create(path.Join(destDir, "_index.md"))
if err != nil {
return err
}
defer outputfile.Close()

return tmpl.Execute(outputfile, struct {
Rules []Rule
}{
Rules: rules,
})
}

func listRules() ([]Rule, error) {
fset := token.NewFileSet()
node, err := parser.ParseFile(fset, "ruleset.go", nil, parser.ParseComments)
Expand All @@ -109,6 +136,7 @@ func listRules() ([]Rule, error) {
case "Name":
if basicLit, ok := kv.Value.(*ast.BasicLit); ok {
rule.Name = strings.Trim(basicLit.Value, `"`)
rule.Filename = fmt.Sprintf("%s.md", camelToKebab(rule.Name))
}
case "Description":
if basicLit, ok := kv.Value.(*ast.BasicLit); ok {
Expand Down
8 changes: 8 additions & 0 deletions frontend/dockerfile/linter/ruleset.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ var (
return fmt.Sprintf("Relative workdir %q can have unexpected results if the base image changes", workdir)
},
}
// TODO: RuleUndefinedArg is not used in the codebase
// RuleUndefinedArg = LinterRule[func(string) string]{
// Name: "UndefinedArg",
// Description: "ARGs should be defined before their use",
// Format: func(arg string) string {
// return fmt.Sprintf("Usage of undefined variable '$%s'", arg)
// },
// }
RuleUndefinedVar = LinterRule[func(string, string) string]{
Name: "UndefinedVar",
Description: "Variables should be defined before their use",
Expand Down

0 comments on commit fb6a825

Please sign in to comment.