Super-Linter Documentation

repository·main·Indexed 27 days ago

https://github.com/super-linter/super-linter

A containerized suite of linters and code analyzers for consistent code validation and formatting across multiple programming languages. It supports parallel execution, integrates with GitHub Actions, and provides a curated set of tools for languages including Python, JavaScript, Go, Rust, and more. Available in standard and slim variants, it is configurable via environment variables to manage file filtering, tool-specific settings, and CI integration.

Tokens
19.3K
Snippets
31
Records
111
Agent score
91%

What's inside Super-Linter

  1. Overview of Super-Linter

    main

    Super-Linter is a ready-to-run, fully-containerized collection of linters and code analyzers designed to validate and fix source code. It helps establish best practices and consistent formatting across multiple programming languages. It reports issues via console output and can integrate with GitHub Actions status checks.

    Key features include:

    • Parallel Execution: Runs linters in parallel (since v6) to scan large repositories quickly.
    • Curated Linters: Uses a highly curated set of tools to reduce bloat and scanning time.
    • Environment Agnostic: Runs on GitHub Actions or any environment with an OCI-compatible container runtime engine (e.g., Docker).
    • Lean Design: Builds on established standards like GNU Parallel.
  2. Install OS packages at runtime

    main

    Super-Linter allows you to install additional Operating System (OS) packages at runtime during each execution. This is achieved by providing a JSON file containing a list of packages, which are then passed to the Alpine Package Keeper (apk add) command.

    To install OS packages:

    1. Create a JSON file containing an array of package names.
    2. Save this file in the LINTER_RULES_PATH directory.
    3. Name the file using the value of the OS_PACKAGES_CONFIG_FILE_NAME environment variable (the default filename is os-packages.json).
    ["package1", "package2", "package3"]
  3. Orchestrate and run a new linter tool

    main

    To integrate the tool into the Super-Linter execution flow:

    1. Register the language: Add a new entry to LANGUAGES_ARRAY in lib/globals/languages.sh. Use the format "<LANGUAGE_NAME>_<TOOL_NAME>" (e.g., PYTHON_RUFF) and keep it alphabetically ordered.
    2. Define the command: In lib/functions/linterCommands.sh, define LINTER_COMMANDS_ARRAY_<LANGUAGE_NAME>.
      • Example: LINTER_COMMANDS_ARRAY_GO_MODULES=(golangci-lint run --allow-parallel-runners)
    3. Handle custom arguments: If users should customize arguments, define <LANGUAGE_NAME>_COMMAND_ARGS and use AddOptionsToCommand to inject them.
    4. Configure Check/Fix modes: In lib/globals/linterCommandsOptions.sh, define options for the tool's specific modes:
      • If the tool is Fix-by-default: Define <LANGUAGE_NAME>_CHECK_ONLY_MODE_OPTIONS=(...).
      • If the tool is Check-only-by-default: Define <LANGUAGE_NAME>_FIX_MODE_OPTIONS=(...).
      • If it supports both, define both.
    <LANGUAGE_NAME>_COMMAND_ARGS="${<LANGUAGE_NAME>_COMMAND_ARGS:-""}"
    if [ -n "${<LANGUAGE_NAME>_COMMAND_ARGS:-}" ]; then
      export <LANGUAGE_NAME>_COMMAND_ARGS
      AddOptionsToCommand "LINTER_COMMANDS_ARRAY_<LANGUAGE_NAME>" "${<LANGUAGE_NAME>_COMMAND_ARGS}"
    fi
  4. Install a new tool via Maven or Java

    main

    To add a Java-based tool:

    1. Create a directory dependencies/<name-of-tool>.
    2. Create dependencies/<name-of-tool>/build.gradle with the following structure:
      repositories {
        mavenLocal()
        mavenCentral()
      }
      
      dependencies {
        implementation 'your:dependency-here:version'
      }
      
      group 'com.github.super-linter'
      version '1.0.0-SNAPSHOT'
    3. Update the dependencies section in that build.gradle to include your specific dependencies.
    4. Add these lines to the Dockerfile to run an installation script:
      COPY scripts/install-<name-of-tool>.sh /
      RUN --mount=type=secret,id=GITHUB_TOKEN /<name-of-tool>.sh && rm -rf /<name-of-tool>.sh
    5. Implement the installation logic in scripts/install-<name-of-tool>.sh. You can extract the version from build.gradle using awk.
    6. Add the tool to the java-gradle group in the Dependabot configuration.
    repositories {
      mavenLocal()
      mavenCentral()
    }
    
    dependencies {
      implementation 'your:dependency-here:version'
    }
    
    group 'com.github.super-linter'
    version '1.0.0-SNAPSHOT'
  5. Upgrade from >=v8.2.0 to v8.4.0

    main

    When upgrading to v8.4.0, note the following changes:

    Remove stylelint-config-sass-guidelines

    stylelint-config-sass-guidelines is no longer shipped.

    Remove Terrascan Support

    Support for Terrascan has been removed. You can remove the following configuration variables:

    • TERRAFORM_TERRASCAN_CONFIG_FILE
    • VALIDATE_TERRAFORM_TERRASCAN
  6. Install a new tool via Docker image

    main

    To add a tool provided as a container image:

    1. Add a new build stage to the Dockerfile:
      FROM your/image:version as <name-of-tool>
    2. Copy the binaries/libraries from the image to the Super-Linter environment:
      COPY --from=<name-of-tool> /usr/local/bin/<name-of-command> /usr/bin/
    3. Add the dependency to the docker group in the Dependabot configuration.
    FROM your/image:version as <name-of-tool>
  7. Configure a new tool's configuration file

    main

    If the new tool does not support automatic configuration file resolution, you must manually set the path:

    1. In lib/globals/linterRules.sh, define the filename variable: <LANGUAGE_NAME>_FILE_NAME="${<LANGUAGE_NAME>_CONFIG_FILE:-"default-config-file-name.conf"}"
    2. Create a minimal configuration file in the TEMPLATES/ directory.
    3. In lib/functions/linterCommands.sh, update the command to use the path: tool-name --config "${<LANGUAGE_NAME>_LINTER_RULES}".

    If the tool does support automatic resolution, add it to the list in README.md under the section describing tools that do not load configuration from LINTER_RULES_PATH.

  8. Set up the development environment with Dev Containers

    main

    For a consistent and reproducible development environment, it is recommended to use Visual Studio Code with the Dev Containers extension. The repository includes a .devcontainer configuration that sets up a container with all necessary dependencies and tools. The devcontainer also includes extensions that run most linters and formatters automatically when you save files.

    To start, open the repository in Visual Studio Code and select "Reopen in Container" when prompted.

  9. Run Super-Linter using Docker

    main

    You can run Super-Linter outside of GitHub Actions using a container runtime engine like Docker. Ensure you mount your local codebase to the /tmp/lint directory within the container and set RUN_LOCAL=true.

    docker run \
      -e LOG_LEVEL=DEBUG \
      -e RUN_LOCAL=true \
      -v /path/to/local/codebase:/tmp/lint \
      ghcr.io/super-linter/super-linter:latest
  10. Populate the file list for a new tool

    main

    To ensure Super-Linter identifies the correct files for your new tool, you must implement logic in lib/functions/buildFileList.sh. Depending on how the tool identifies files, choose one of the following three approaches:

    1. File extension or name check

    Use this if the tool targets specific extensions. Add an elif clause to the BuildFileArrays function in lib/functions/buildFileList.sh. You can use these variables:

    • FILE_TYPE: the file extension.
    • BASE_FILE: the name of the file.
    • FILE_DIR_NAME: the directory path.

    2. File contents check

    Use this if you need to inspect file contents to determine if the tool should run.

    1. Implement a detection function in lib/functions/detectFiles.sh.
    2. Add an elif clause in the BuildFileArrays function in lib/functions/buildFileList.sh that calls your detection function.

    3. Entire workspace check

    Use this if the tool lints the entire workspace (e.g., via a configuration file).

    1. Add logic to the BuildFileList function in lib/functions/buildFileList.sh to handle the workspace test case.
    2. In BuildFileArrays, add the file to the language-specific array when "${FILE}" == "${GITHUB_WORKSPACE}".
    3. Update the README to include the tool in the list of tools that check the entire workspace.

    Tip: To optimize performance, combine extension checks with content checks (e.g., only run content detection on .yaml files).

    # Example: Extension check
    elif [ "${FILE_TYPE}" == "ext" ]; then
      echo "${FILE}" >>"${FILE_ARRAYS_DIRECTORY_PATH}/file-array-<LANGUAGE_NAME>"
    fi
    
    # Example: Content check
    elif DetectCloudFormationFile "${FILE}"; then
      echo "${FILE}" >>"${FILE_ARRAYS_DIRECTORY_PATH}/file-array-CLOUDFORMATION"
    fi
  11. Implement a fallback for file type detection

    main

    If your tool requires the CheckFileType fallback (using the GNU file utility) in lib/functions/buildFileList.sh, follow these steps:

    1. Create a helper function: In lib/functions/buildFileList.sh, create AddTo<Language name>FileArrays (where <Language name> is lowercase). This function should append the file to all relevant language arrays.
    2. Export the function: Add export -f AddTo<Language name>FileArrays at the bottom of lib/functions/buildFileList.sh.
    3. Refactor extension checks: Update the BuildFileArrays function to call your new helper instead of appending directly.
    4. Extend CheckFileType: Add a case to the CheckFileType function to match the output of the file command.
    5. Update tests: Add a case to CheckFileTypeTest in test/lib/buildFileListTest.sh.
    # 1. Define helper
    AddToPythonFileArrays() {
      local FILE="${1}"
      echo "${FILE}" >>"${FILE_ARRAYS_DIRECTORY_PATH}/file-array-PYTHON_BLACK"
      echo "${FILE}" >>"${FILE_ARRAYS_DIRECTORY_PATH}/file-array-PYTHON_FLAKE8"
    }
    
    # 2. Export helper
    export -f AddToPythonFileArrays
    
    # 3. Refactor extension check
    elif [ "${FILE_TYPE}" == "py" ]; then
      AddToPythonFileArrays "${FILE}"
    fi
    
    # 4. Extend CheckFileType
    *"Python script"*)
      FILE_TYPE_MESSAGE="Found Python script without extension: ${FILE}"
      AddToPythonFileArrays "${FILE}"
      ;;