103 lines
4.2 KiB
YAML
103 lines
4.2 KiB
YAML
# Lint gates, each switched on by the files present in the calling repo.
|
|
#
|
|
# shell scripts shellcheck (*.sh, *.bash)
|
|
# Python ruff check (repo's ruff/pyproject config if any)
|
|
# Dockerfiles hadolint (repo's .hadolint.yaml if any)
|
|
# YAML yamllint (repo's .yamllint if any, else relaxed)
|
|
# CI workflows actionlint (.forgejo/ and .github/ workflows)
|
|
# OpenTofu/HCL tofu fmt + tflint (repo's .tflint.hcl if any)
|
|
#
|
|
# Every linter runs even if an earlier one failed, so one push shows every
|
|
# problem; the job fails if any of them did. Turn one off with its input.
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
shellcheck:
|
|
type: boolean
|
|
default: true
|
|
shellcheck-severity:
|
|
description: Lowest shellcheck severity that fails the job (error, warning, info, style).
|
|
type: string
|
|
default: warning
|
|
ruff:
|
|
type: boolean
|
|
default: true
|
|
ruff-format:
|
|
description: Also require `ruff format --check` to pass.
|
|
type: boolean
|
|
default: false
|
|
hadolint:
|
|
type: boolean
|
|
default: true
|
|
yamllint:
|
|
type: boolean
|
|
default: true
|
|
actionlint:
|
|
type: boolean
|
|
default: true
|
|
terraform:
|
|
type: boolean
|
|
default: true
|
|
|
|
jobs:
|
|
lint:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
|
|
- name: shellcheck
|
|
if: ${{ !cancelled() && inputs.shellcheck }}
|
|
env:
|
|
SEVERITY: ${{ inputs.shellcheck-severity }}
|
|
run: |
|
|
if [ -z "$(git ls-files '*.sh' '*.bash')" ]; then echo "No shell scripts; skipping."; exit 0; fi
|
|
git ls-files -z '*.sh' '*.bash' | xargs -0 shellcheck --severity="$SEVERITY"
|
|
|
|
- name: ruff
|
|
if: ${{ !cancelled() && inputs.ruff }}
|
|
env:
|
|
FORMAT: ${{ inputs.ruff-format }}
|
|
run: |
|
|
if [ -z "$(git ls-files '*.py' '*.pyi')" ]; then echo "No Python; skipping."; exit 0; fi
|
|
ruff --version
|
|
ruff check --output-format=full .
|
|
if [ "$FORMAT" = "true" ]; then ruff format --check .; fi
|
|
|
|
- name: hadolint
|
|
if: ${{ !cancelled() && inputs.hadolint }}
|
|
run: |
|
|
set -- 'Dockerfile' '*/Dockerfile' 'Dockerfile.*' '*/Dockerfile.*' '*.Dockerfile' 'Containerfile' '*/Containerfile'
|
|
if [ -z "$(git ls-files "$@")" ]; then echo "No Dockerfiles; skipping."; exit 0; fi
|
|
git ls-files -z "$@" | xargs -0 hadolint --failure-threshold warning
|
|
|
|
- name: yamllint
|
|
if: ${{ !cancelled() && inputs.yamllint }}
|
|
run: |
|
|
if [ -z "$(git ls-files '*.yml' '*.yaml')" ]; then echo "No YAML; skipping."; exit 0; fi
|
|
cfg=""
|
|
for f in .yamllint .yamllint.yml .yamllint.yaml; do if [ -f "$f" ]; then cfg="$f"; fi; done
|
|
# Without a repo config: relaxed rules, and no line-length check,
|
|
# which mostly flags long URLs and Kubernetes annotations.
|
|
if [ -n "$cfg" ]; then set -- -c "$cfg"
|
|
else set -- -d '{extends: relaxed, rules: {line-length: disable}}'; fi
|
|
git ls-files -z '*.yml' '*.yaml' | xargs -0 yamllint -f parsable "$@"
|
|
|
|
- name: actionlint
|
|
if: ${{ !cancelled() && inputs.actionlint }}
|
|
run: |
|
|
set -- '.forgejo/workflows/*.yml' '.forgejo/workflows/*.yaml' '.github/workflows/*.yml' '.github/workflows/*.yaml'
|
|
if [ -z "$(git ls-files "$@")" ]; then echo "No workflow files; skipping."; exit 0; fi
|
|
# Forgejo needs runs-on on a job that calls a cross-repo reusable
|
|
# workflow (the runner expands it, not the server), which GitHub
|
|
# forbids. Ignore that one GitHub-only rule.
|
|
git ls-files -z "$@" | xargs -0 actionlint -shellcheck= -ignore '"runs-on" is not available'
|
|
|
|
- name: OpenTofu fmt and tflint
|
|
if: ${{ !cancelled() && inputs.terraform }}
|
|
run: |
|
|
if [ -z "$(git ls-files '*.tf')" ]; then echo "No .tf files; skipping."; exit 0; fi
|
|
rc=0
|
|
tofu fmt -check -recursive -diff || rc=1
|
|
if [ -f .tflint.hcl ]; then tflint --init; fi
|
|
tflint --recursive --format compact || rc=1
|
|
exit "$rc"
|