Skip to content

Commit

Permalink
feat: add dockerfile linting (#382)
Browse files Browse the repository at this point in the history
Co-authored-by: Jorge Martínez <[email protected]>
Co-authored-by: Maxime Rey <[email protected]>
Co-authored-by: Roberto Pastor Muela <[email protected]>
Also thanks to germa89 for his feedback
  • Loading branch information
SMoraisAnsys authored Feb 12, 2024
1 parent 0fcf2ba commit 3029563
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 1 deletion.
60 changes: 59 additions & 1 deletion code-style/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ description: >
This action evaluates the code quality of your project by using `pre-commit
<https://github.com/pre-commit/pre-commit/>`_. The action installs and runs
``pre-commit``. It is assumed that your project contains a
``.pre-commit-config.yaml`` file in the root directory.
``.pre-commit-config.yaml`` file in the root directory. The action can also
be extended to lint docker files that are contained in the docker directory and the .devcontainer directory.
.. warning::
If docker lint is enabled and directories docker or .devcontainer exist,
the action will fail if it doesn't find a Dockerfile.
inputs:

Expand All @@ -27,6 +34,29 @@ inputs:
default: true
type: boolean

docker-lint:
description: >
Extend the workflow to lint Dockerfile(s).
required: false
default: false
type: bool

docker-recursive:
description: >
Search for Dockerfile(s) recursively. Only applies to allowed
directories, i.e. docker and .devcontainer.
required: false
default: false
type: bool

docker-error-level:
description: >
Fail docker-style action based on hadolint output (-1: never, 0: error,
1: warning, 2: info)
required: false
default: 2
type: int

runs:
using: "composite"
steps:
Expand All @@ -49,3 +79,31 @@ runs:
- name: "Run pre-commit"
shell: bash
run: pre-commit run --all-files --show-diff-on-failure

# ------------------------------------------------------------------------

# Trigger docker-style action if docker-lint is set to true.
- uses: ansys/actions/_logging@main
if: inputs.docker-lint == 'true'
with:
level: "INFO"
message: >
Extend the workflow to lint Dockerfile(s).
- name: "Run Dockerfile linting in directories 'docker' and '.devcontainer'"
if: inputs.docker-lint == 'true'
uses: ansys/actions/docker-style@main
with:
directory: "docker .devcontainer"
recursive: ${{ inputs.docker-recursive }}
error-level: ${{ inputs.docker-error-level }}

# ------------------------------------------------------------------------

# End action as docker-lint is set to false.
- uses: ansys/actions/_logging@main
if: ${{ inputs.docker-lint == 'false' }}
with:
level: "INFO"
message: >
Docker lint disabled.
9 changes: 9 additions & 0 deletions doc/source/style-actions/examples/docker-style-basic.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
docker-style:
name: "Docker style"
runs-on: ubuntu-latest
steps:
- uses: ansys/actions/docker-style@{{ version }}
with:
directory: docker
recursive: true
error-level: 1
24 changes: 24 additions & 0 deletions doc/source/style-actions/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ with PyAnsys guidelines.

Code style action
-----------------

.. jinja:: code-style

{{ description }}
Expand All @@ -27,6 +28,7 @@ Code style action

Doc style action
----------------

.. jinja:: doc-style

{{ description }}
Expand All @@ -46,6 +48,28 @@ Doc style action
{% endfor %}


Docker style action
-------------------

.. jinja:: docker-style

{{ description }}

{{ inputs_table }}

Examples
++++++++

{% for filename, title in examples %}
.. dropdown:: {{ title }}
:animate: fade-in

.. literalinclude:: examples/{{ filename }}
:language: yaml

{% endfor %}


Commit style action
-------------------

Expand Down
157 changes: 157 additions & 0 deletions docker-style/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
name: >
Lint Dockerfile
description: >
Evaluate the quality of your project Dockerfile(s) by using `hadolint
<https://github.com/hadolint/hadolint/>`_. This action can be used to
lint Dockerfile(s) from multiple directories, see input "directory"
description. The action uses `hadolint-gh-action
<https://github.com/jbergstroem/hadolint-gh-action>`_ behind the scenes.
If you want to evaluate multiple Dockerfiles contained in various
directories of the provided directory, use the recursive option.
When linting a Dockerfile dedicated to Windows, one should use hadolint
shell pragma to avoid false positives from ShellCheck, see `hadolint shell pragma
<https://github.com/hadolint/hadolint/pull/708>`_.
.. note::
This action emphasizes the fact of having Dockerfile(s) contained inside the
'docker' directory in the root of the project.
.. warning::
This action only looks for docker files named Dockerfile.
A docker file like Dockerfile.linux will not be linted.
inputs:

# Optional inputs

directory:
description: >
Directory from which to search for Dockerfile(s). You can pass multiple
directories for processing by separating them with spaces, e.g.
"docker .devcontainer".
required: false
default: docker
type: string

recursive:
description: >
Search for Dockerfile(s) recursively.
required: false
default: false
type: bool

error-level:
description: >
Fail action based on hadolint output (-1: never, 0: error, 1: warning,
2: info)
required: false
default: 2
type: int

runs:
using: "composite"
steps:

# ------------------------------------------------------------------------

- uses: ansys/actions/_logging@main
with:
level: "INFO"
message: >
Check that directory 'docker' exists at the root of the repository.
If it does not, then a warning is emitted.
- name: "Check if docker directory exists"
shell: bash
run: |
if [ -d "${{ github.workspace }}/docker" ]; then
echo "HAS_DOCKER_DIR=true" >> $GITHUB_ENV
else
echo "HAS_DOCKER_DIR=false" >> $GITHUB_ENV
fi
# ------------------------------------------------------------------------

- uses: ansys/actions/_logging@main
if: env.HAS_DOCKER_DIR == 'false'
with:
level: "WARNING"
message: >
No 'docker' directory found. If possible, please follow the common
approach of storing docker files in the 'docker' directory at the
root of the repository.
# ------------------------------------------------------------------------

- uses: ansys/actions/_logging@main
with:
level: "INFO"
message: >
Check that directory input exist. If not, a warning is raised and
non existing ones (if any) are ignored.
- name: "Filter input directory"
shell: bash
run: |
EXISTING_DIRS=""
NON_EXISTING_DIRS=""
for directory in ${{ inputs.directory }}
do
if [ -d "${{ github.workspace }}/$directory" ]; then
EXISTING_DIRS+="$directory "
else
NON_EXISTING_DIRS+="$directory "
fi
done
EXISTING_DIRS=$(echo -n "$EXISTING_DIRS" | xargs)
echo "EXISTING_DIRS=$EXISTING_DIRS" >> $GITHUB_ENV
NON_EXISTING_DIRS=$(echo -n "$NON_EXISTING_DIRS" | xargs)
echo "NON_EXISTING_DIRS=$NON_EXISTING_DIRS" >> $GITHUB_ENV
# ------------------------------------------------------------------------

- uses: ansys/actions/_logging@main
if: ${{ !!env.EXISTING_DIRS }}
with:
level: "INFO"
message: >
Lint '${{ env.EXISTING_DIRS }}'.
- name: "Format Hadolint dockerfile input"
if: ${{ !!env.EXISTING_DIRS }}
shell: bash
run: |
fmt_directory="${{ env.EXISTING_DIRS }}"
pattern="${{ inputs.recursive == 'true' && '/**' || '' }}/Dockerfile"
fmt_directory_array=($fmt_directory)
for i in "${!fmt_directory_array[@]}"; do
fmt_directory_array[i]="${fmt_directory_array[i]}${pattern}"
done
fmt_directory="${fmt_directory_array[*]}"
echo "FORMATED_HADOLINT_DOCKERFILE_INPUT=$fmt_directory" >> $GITHUB_ENV
- name: "Run Hadolint"
if: ${{ !!env.EXISTING_DIRS }}
uses: jbergstroem/hadolint-gh-action@v1
with:
dockerfile: ${{ env.FORMATED_HADOLINT_DOCKERFILE_INPUT }}
error_level: ${{ inputs.error-level }}

# ------------------------------------------------------------------------

- uses: ansys/actions/_logging@main
if: ${{ env.NON_EXISTING_DIRS != '' && contains(env.NON_EXISTING_DIRS, ' ') }}
with:
level: "WARNING"
message: >
Non existing directories: '${{ env.NON_EXISTING_DIRS }}'
- uses: ansys/actions/_logging@main
if: ${{ env.NON_EXISTING_DIRS != '' && !contains(env.NON_EXISTING_DIRS, ' ') }}
with:
level: "WARNING"
message: >
Non existing directory: '${{ env.NON_EXISTING_DIRS }}'

0 comments on commit 3029563

Please sign in to comment.