diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..51605a9 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,4 @@ +# https://help.github.com/en/articles/displaying-a-sponsor-button-in-your-repository +github: brpaz +patreon: brpaz +custom: https://www.buymeacoffee.com/Z1Bu6asGV diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 82dd81d..0000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,10 +0,0 @@ -version: 2 -updates: -- package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "daily" -- package-ecosystem: "docker" - directory: "/" - schedule: - interval: "daily" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3a5f201..cd6b701 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,139 +3,81 @@ on: push: branches: - master - pull_request: env: TEST_IMAGE_NAME: hadolint-action:${{github.sha}} -permissions: - contents: write - issues: write # Used by Release step to update "The automated release is failing" issue - pull-requests: write # Used by ShellCheck Action to add comments on PR - jobs: lint: - name: Lint - runs-on: ubuntu-24.04 - container: pipelinecomponents/hadolint:0.27.2 + runs-on: ubuntu-latest + container: pipelinecomponents/hadolint:latest steps: - - uses: actions/checkout@v5 - + - uses: actions/checkout@v1 - name: Run hadolint run: hadolint Dockerfile - shellcheck: - name: ShellCheck - runs-on: ubuntu-24.04 + build: + runs-on: ubuntu-latest + needs: ['lint'] steps: - - uses: actions/checkout@v5 - - - name: Run ShellCheck - uses: reviewdog/action-shellcheck@v1.31.0 - with: - reporter: github-pr-review - fail_on_error: true - - build-test: - name: Build and Test - runs-on: ubuntu-24.04 - needs: - - lint - - shellcheck - steps: - - uses: actions/checkout@v5 - + - uses: actions/checkout@v1 - name: Build Docker image run: docker build -t $TEST_IMAGE_NAME . - - name: Run Structure tests - uses: brpaz/structure-tests-action@v1.1.2 + - name: Save Docker image artifact + run: docker save -o action.tar $TEST_IMAGE_NAME + + - name: Upload image artifact + uses: actions/upload-artifact@master with: - image: ${{ env.TEST_IMAGE_NAME }} + name: action-image + path: action.tar - integration-tests: - name: Integration Tests - runs-on: ubuntu-24.04 - needs: - - build-test + test: + name: Unit Tests + runs-on: ubuntu-latest + needs: build steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v1 - - name: Run integration test 1 + - name: Pull Image artifact + uses: actions/download-artifact@master + with: + name: action-image + + - name: Load image into docker context + run: docker load -i action-image/action.tar + + - name: Get Image Name + id: image_name + run: echo "##[set-output name=image;]$(echo $TEST_IMAGE_NAME)" + + - name: Run Structure tests + uses: brpaz/structure-tests-action@master + with: + image: ${{ steps.image_name.outputs.image }} + + integration: + name: Integration Tests + runs-on: ubuntu-latest + needs: test + steps: + - uses: actions/checkout@v1 + + - name: Run integration test uses: ./ with: dockerfile: testdata/Dockerfile - - name: Run integration test 2 - ignore a rule - # This step is supposed to print out an info level rule violation - # but completely ignore the two rules listed below - uses: ./ - with: - dockerfile: testdata/warning.Dockerfile - ignore: 'DL3014,DL3008' - no-fail: true - - - name: Run integration test 3 - set failure threshold - # This step will print out an info level rule violation, but not fail - # because of the high failure threshold. - uses: ./ - with: - dockerfile: testdata/info.Dockerfile - failure-threshold: warning - - - name: Run integration test 4 - output format - # This step will never fail, but will print out rule violations as json. - uses: ./ - with: - dockerfile: testdata/warning.Dockerfile - failure-threshold: error - format: json - - - name: Run integration test 5 - config file - # This step will never fail, but will print out rule violations - # because in config is set the error failure threshold. - id: hadolint5 - uses: ./ - with: - dockerfile: testdata/warning.Dockerfile - config: testdata/hadolint.yaml - - - name: Run integration test 6 - verify results output parameter - # This step will never fail, but will print out the results from step5 - env: - results: ${{ steps.hadolint5.outputs.results }} - run: echo "$results" - - - name: Run integration test 7 - set recursive - # This step will never fail, but will print out rule violations - # for all the Dockerfiles in repository. - uses: ./ - with: - dockerfile: "*Dockerfile" - failure-threshold: error - recursive: true - - #- name: Run integration test 8 - output to file - # # This step will never fail, but will print out rule violations. - # uses: ./ - # with: - # dockerfile: testdata/warning.Dockerfile - # format: sarif - # output-file: report.sarif - release: if: github.event_name == 'push' && github.ref == 'refs/heads/master' name: Release - runs-on: ubuntu-24.04 - needs: - - integration-tests + runs-on: ubuntu-latest + needs: integration steps: - - uses: actions/checkout@v5 - - - uses: cycjimmy/semantic-release-action@v5 - with: - extra_plugins: | - @semantic-release/git + - uses: actions/checkout@v1 + - name: Semantic Release + uses: brpaz/action-semantic-release@master env: GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/Dockerfile b/Dockerfile index 93a3909..8202bf2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -FROM ghcr.io/hadolint/hadolint:v2.14.0-debian +FROM hadolint/hadolint:v1.17.5-alpine -COPY LICENSE README.md problem-matcher.json / -COPY hadolint.sh /usr/local/bin/hadolint.sh +COPY LICENSE README.md / + +ENTRYPOINT [ "hadolint" ] -ENTRYPOINT [ "/usr/local/bin/hadolint.sh" ] diff --git a/Makefile b/Makefile index a35729b..32cdadb 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ IMAGE_NAME:=hadolint-action -lint-dockerfile: ## Runs hadolint against application dockerfile +lint-dockerfile: ## Runs hadoint against application dockerfile @docker run --rm -v "$(PWD):/data" -w "/data" hadolint/hadolint hadolint Dockerfile lint-yaml: ## Lints yaml configurations @@ -12,8 +12,8 @@ build: ## Builds the docker image test: build ## Runs a test in the image @docker run -i --rm \ - -v /var/run/docker.sock:/var/run/docker.sock \ - -v ${PWD}:/test zemanlx/container-structure-test:v1.8.0-alpine \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v ${PWD}:/test zemanlx/container-structure-test:v1.8.0-alpine \ test \ --image $(IMAGE_NAME) \ --config test/structure-tests.yaml diff --git a/README.md b/README.md index 0ecee3f..c6f8c06 100644 --- a/README.md +++ b/README.md @@ -1,76 +1,26 @@ -# Hadolint Action +# Hadolint GitHub Action -> GitHub Action that runs [Hadolint](https://github.com/hadolint/hadolint) Dockerfile linting tool. +> Action that runs [Hadolint](https://github.com/hadolint/hadolint) Dockerfile linting tool. [![GitHub Action](https://img.shields.io/badge/GitHub-Action-blue?style=for-the-badge)](https://github.com/features/actions) [![License](https://img.shields.io/badge/License-MIT-yellow.svg?style=for-the-badge)](LICENSE) [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg?style=for-the-badge)](http://commitizen.github.io/cz-cli/) [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=for-the-badge)](https://github.com/semantic-release/semantic-release?style=for-the-badge) -[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/hadolint/hadolint-action/ci.yml?branch=master&style=for-the-badge)](https://github.com/hadolint/hadolint-action/action) +[![GitHub Actions](https://github.com/brpaz/hadolint-action/workflows/CI/badge.svg?style=for-the-badge)](https://github.com/brpaz/hadolint-action/actions) ## Usage -Add the following step to your workflow configuration: - ```yml steps: - - uses: actions/checkout@v3 - - uses: hadolint/hadolint-action@v3.1.0 - with: - dockerfile: Dockerfile + uses: brpaz/hadolint-action@master ``` ## Inputs -| Name | Description | Default | -|----------------------|-----------------------------------------------------------------------------------------------------------------------------------------|--------------------| -| `dockerfile` | The path to the Dockerfile to be tested | `./Dockerfile` | -| `recursive` | Search for specified dockerfile
recursively, from the project root | `false` | -| `config` | Custom path to a Hadolint config file | `./.hadolint.yaml` | -| `output-file` | A sub-path where to save the
output as a file to | `/dev/stdout` | -| `no-color` | Don't create colored output (`true`/`false`) | `false` | -| `no-fail` | Never fail the action (`true`/`false`) | `false` | -| `verbose` | Output more information (`true`/`false`) | `false` | -| `format` | The output format. One of [`tty` \| `json` \|
`checkstyle` \| `codeclimate` \|
`gitlab_codeclimate` \| `codacy` \| `sarif`] | `tty` | -| `failure-threshold` | Rule severity threshold for pipeline
failure. One of [`error` \| `warning` \|
`info` \| `style` \| `ignore`] | `info` | -| `override-error` | Comma separated list of rules to treat with `error` severity | | -| `override-warning` | Comma separated list of rules to treat with `warning` severity | | -| `override-info` | Comma separated list of rules to treat with `info` severity | | -| `override-style` | Comma separated list of rules to treat with `style` severity | | -| `ignore` | Comma separated list of Hadolint rules to ignore. | | -| `trusted-registries` | Comma separated list of urls of trusted registries | | +**`dockerfile`** -## Output - -The Action will store results in an environment variable that can be used in other steps in a workflow. - -Example to create a comment in a PR: - -``` -- name: Update Pull Request - uses: actions/github-script@v6 - if: github.event_name == 'pull_request' - with: - script: | - const output = ` - #### Hadolint: \`${{ steps.hadolint.outcome }}\` - \`\`\` - ${process.env.HADOLINT_RESULTS} - \`\`\` - `; - - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: output - }) -``` - -## Hadolint Configuration - -To configure Hadolint (for example ignore rules), you can create an `.hadolint.yaml` file in the root of your repository. Please check the Hadolint [documentation](https://github.com/hadolint/hadolint#configure). +The path to the Dockerfile to be tested. By default it will look for a Dockerfile in the current directory. ## 🤝 Contributing @@ -82,13 +32,10 @@ Contributions are what make the open source community such an amazing place to b 4. Push to the Branch (`git push origin feature/AmazingFeature`) 5. Open a Pull Request -## 💛 Support the project +## Useful Resources -If this project was useful to you in some form, We would be glad to have your support. It will help keeping the project alive. - -The sinplest form of support is to give a ⭐️ to this repo. - -This project was originally created by [Bruno Paz](https://github.com/sponsors/brpaz) and incorporated into the Hadolint organization. If you appreciate the work done on this action, Bruno would be happy with your [sponsorship](https://github.com/sponsors/brpaz). +* [Building actions - GitHub Help](https://help.github.com/en/articles/building-actions) +* [actions/toolkit: The GitHub ToolKit for developing GitHub Actions.](https://github.com/actions/toolkit) ## Author @@ -99,4 +46,6 @@ This project was originally created by [Bruno Paz](https://github.com/sponsors/b ## 📝 License -[MIT](LICENSE) +Copyright © 2019 [Bruno Paz](https://github.com/brpaz). + +This project is [MIT](LICENSE) licensed. diff --git a/action.yml b/action.yml index e1c9fba..2a27000 100644 --- a/action.yml +++ b/action.yml @@ -3,98 +3,13 @@ description: 'Action that runs Hadolint Dockerfile linting tool' author: 'Bruno Paz' inputs: dockerfile: - required: false description: 'The path to the Dockerfile to lint' default: 'Dockerfile' - config: - required: false - description: 'Path to a config file' - default: - recursive: - required: false - description: - 'Search for specified dockerfile recursively, from the project root' - default: 'false' - output-file: - required: false - description: 'The path where to save the linting results to' - default: "/dev/stdout" - - # standart hadolint options: - no-color: - required: false - description: Don't create colored output. - default: 'false' - no-fail: - required: false - description: Never exit with a failure status code - default: 'false' - verbose: - required: false - description: Print more information about the running config - default: 'false' - format: - required: false - description: | - The output format, one of [tty (default) | json | checkstyle | - codeclimate | gitlab_codeclimate | codacy | sarif] - default: 'tty' - failure-threshold: - required: false - description: | - Fail the pipeline only if rules with severity above this threshold are - violated. One of [error | warning | info (default) | style | ignore] - default: 'info' - override-error: - required: false - description: - 'A comma separated list of rules whose severity will be `error`' - default: - override-warning: - required: false - description: - 'A comma separated list of rules whose severity will be `warning`' - default: - override-info: - required: false - description: - 'A comma separated list of rules whose severity will be `info`' - default: - override-style: - required: false - description: - 'A comma separated list of rules whose severity will be `style`' - default: - ignore: - required: false - description: 'A comma separated string of rules to ignore' - default: - trusted-registries: - required: false - description: 'A comma separated list of trusted registry urls' - default: - runs: using: 'docker' image: 'Dockerfile' args: - ${{ inputs.dockerfile }} - env: - NO_COLOR: ${{ inputs.no-color }} - HADOLINT_NOFAIL: ${{ inputs.no-fail }} - HADOLINT_VERBOSE: ${{ inputs.verbose }} - HADOLINT_FORMAT: ${{ inputs.format }} - HADOLINT_FAILURE_THRESHOLD: ${{ inputs.failure-threshold }} - HADOLINT_OVERRIDE_ERROR: ${{ inputs.override-error }} - HADOLINT_OVERRIDE_WARNING: ${{ inputs.override-warning }} - HADOLINT_OVERRIDE_INFO: ${{ inputs.override-info }} - HADOLINT_OVERRIDE_STYLE: ${{ inputs.override-style }} - HADOLINT_IGNORE: ${{ inputs.ignore }} - HADOLINT_TRUSTED_REGISTRIES: ${{ inputs.trusted-registries }} - - HADOLINT_CONFIG: ${{ inputs.config }} - HADOLINT_RECURSIVE: ${{ inputs.recursive }} - HADOLINT_OUTPUT: ${{ inputs.output-file }} branding: icon: 'layers' color: 'purple' diff --git a/hadolint.sh b/hadolint.sh deleted file mode 100755 index d28035d..0000000 --- a/hadolint.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/bash -# The problem-matcher definition must be present in the repository -# checkout (outside the Docker container running hadolint). We copy -# problem-matcher.json to the home folder. - -PROBLEM_MATCHER_FILE="/problem-matcher.json" -if [ -f "$PROBLEM_MATCHER_FILE" ]; then - cp "$PROBLEM_MATCHER_FILE" "$HOME/" -fi -# After the run has finished we remove the problem-matcher.json from -# the repository so we don't leave the checkout dirty. We also remove -# the matcher so it won't take effect in later steps. -# shellcheck disable=SC2317 -cleanup() { - echo "::remove-matcher owner=brpaz/hadolint-action::" -} -trap cleanup EXIT - -echo "::add-matcher::$HOME/problem-matcher.json" - -if [ -n "$HADOLINT_CONFIG" ]; then - HADOLINT_CONFIG="-c ${HADOLINT_CONFIG}" -fi - -if [ -z "$HADOLINT_TRUSTED_REGISTRIES" ]; then - unset HADOLINT_TRUSTED_REGISTRIES -fi - -COMMAND="hadolint $HADOLINT_CONFIG" - -if [ "$HADOLINT_RECURSIVE" = "true" ]; then - shopt -s globstar - - filename="${!#}" - flags="${*:1:$#-1}" - - RESULTS=$(eval "$COMMAND $flags" -- **/"$filename") -else - flags=$* - RESULTS=$(eval "$COMMAND" "$flags") -fi -FAILED=$? - -if [ -n "$HADOLINT_OUTPUT" ]; then - if [ -f "$HADOLINT_OUTPUT" ]; then - HADOLINT_OUTPUT="$TMP_FOLDER/$HADOLINT_OUTPUT" - fi - echo "$RESULTS" >"$HADOLINT_OUTPUT" -fi - -RESULTS="${RESULTS//$'\\n'/''}" - -{ - echo "results<>"$GITHUB_OUTPUT" - -{ - echo "HADOLINT_RESULTS<>"$GITHUB_ENV" - -[ -z "$HADOLINT_OUTPUT" ] || echo "Hadolint output saved to: $HADOLINT_OUTPUT" - -exit $FAILED diff --git a/problem-matcher.json b/problem-matcher.json deleted file mode 100644 index 215a6e0..0000000 --- a/problem-matcher.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "problemMatcher": [ - { - "owner": "brpaz/hadolint-action", - "pattern": [ - { - "regexp": "(.*)\\:(\\d+)\\s(.*)", - "file": 1, - "line": 2, - "message": 3 - } - ] - } - ] -} diff --git a/testdata/hadolint.yaml b/testdata/hadolint.yaml deleted file mode 100644 index f8cbb9d..0000000 --- a/testdata/hadolint.yaml +++ /dev/null @@ -1 +0,0 @@ -failure-threshold: error diff --git a/testdata/info.Dockerfile b/testdata/info.Dockerfile deleted file mode 100644 index 3f9ed7c..0000000 --- a/testdata/info.Dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -FROM debian:buster - -# info level warning expected here: -RUN echo "Hello" -RUN echo "World" diff --git a/testdata/warning.Dockerfile b/testdata/warning.Dockerfile deleted file mode 100644 index 24b6d2e..0000000 --- a/testdata/warning.Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM debian:buster - -# emits an info and a warning level violation. -RUN apt-get install foo