Skip to content

CI integration

iglint is a single binary with a clear exit status, so any CI system can run it. What differs is how findings are shown: as annotations on the pull request, in a code scanning dashboard, or in a test report. Pick the matching --output-format (all formats are described in Output formats).

Terminal window
iglint check
  • Exit status 0: no finding at or above the --error-on level (default warning).
  • Exit status 1: at least one such finding.
  • Exit status 2: usage, configuration or internal error.

Useful variations:

Option Effect
--error-on error (or --ignore-warnings) only errors fail the build
--error-on info every finding fails the build
--exit-zero never fail on findings (for a report-only job)
-o FILE / --output-file FILE write the report to a file instead of standard output
-q / --quiet findings only, no summary
--no-cache do not read or write .iglint_cache (see caching in CI)

On an existing project, commit a baseline first so that only new findings fail.

The examples below download the Linux x86_64 binary of a pinned release from GitHub releases (it is statically linked and runs on any Linux image) and put it on the PATH. The archive iglint-linux-x64.tar.gz holds a directory of the same name with the iglint binary. Change the version in one place to upgrade. The release's SHA256SUMS file holds the checksum of every archive, which the GitHub Actions example checks; for a stronger check, compare against a hash you recorded yourself.

In an image with Python, pip install iglint==0.1.0 does the same.

Annotations on the changed lines of a pull request, plus code scanning alerts:

.github/workflows/iglint.yml
name: iglint
on: [pull_request, push]
jobs:
iglint:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write # only for the SARIF upload
steps:
- uses: actions/checkout@v4
- name: Install iglint
env:
IGLINT_VERSION: v0.1.0
run: |
cd "$RUNNER_TEMP"
url="https://github.com/Mustry-Solutions/iglint/releases/download/${IGLINT_VERSION}"
curl -sSfLO "$url/iglint-linux-x64.tar.gz"
curl -sSfLO "$url/SHA256SUMS"
sha256sum -c --ignore-missing SHA256SUMS
tar -xzf iglint-linux-x64.tar.gz
echo "$RUNNER_TEMP/iglint-linux-x64" >> "$GITHUB_PATH"
# Annotations, and the gate.
- run: iglint check --output-format github
# Code scanning (optional): a SARIF report, uploaded even when the gate failed.
- run: iglint check --output-format sarif --output-file iglint.sarif --exit-zero
if: always()
- uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: iglint.sarif

The github format prints workflow commands, which GitHub turns into annotations:

::error file=projects/demo-hmi/com.inductiveautomation.perspective/views/Line/Overview/view.json,line=84,col=75,endLine=84,endColumn=94,title=REF001::View `Line/PumpDetial` does not exist
::warning file=projects/demo-hmi/com.inductiveautomation.perspective/views/Line/Overview/view.json,line=56,col=43,endLine=56,endColumn=46,title=BIND004::`now` polls every 1000 ms, faster than the minimum of 10000 ms

Errors become ::error, warnings ::warning and info findings ::notice.

GitLab shows Code Quality reports in merge requests:

.gitlab-ci.yml
iglint:
image: python:3.12 # any Linux image with curl
variables:
IGLINT_VERSION: v0.1.0
script:
- curl -sSfL -o /tmp/iglint.tar.gz "https://github.com/Mustry-Solutions/iglint/releases/download/${IGLINT_VERSION}/iglint-linux-x64.tar.gz"
- tar -xzf /tmp/iglint.tar.gz -C /usr/local/bin --strip-components=1 iglint-linux-x64/iglint
- iglint check --output-format gitlab --output-file gl-code-quality-report.json
artifacts:
when: always
reports:
codequality: gl-code-quality-report.json

The azure format prints ##vso[task.logissue] logging commands, which show up as errors and warnings in the build summary:

azure-pipelines.yml
pool:
vmImage: ubuntu-latest
variables:
IGLINT_VERSION: v0.1.0
steps:
- script: |
curl -sSfL "https://github.com/Mustry-Solutions/iglint/releases/download/$(IGLINT_VERSION)/iglint-linux-x64.tar.gz" \
| tar -xz -C "$(Agent.TempDirectory)"
echo "##vso[task.prependpath]$(Agent.TempDirectory)/iglint-linux-x64"
displayName: Install iglint
- script: iglint check --output-format azure
displayName: iglint
##vso[task.logissue type=error;sourcepath=projects/demo-hmi/com.inductiveautomation.perspective/views/Line/Overview/view.json;linenumber=84;columnnumber=75;code=REF001]View `Line/PumpDetial` does not exist

To also publish the findings as test results, add a JUnit report:

- script: iglint check --output-format junit --output-file iglint-junit.xml --exit-zero
displayName: iglint (JUnit report)
condition: always()
- task: PublishTestResults@2
condition: always()
inputs:
testResultsFormat: JUnit
testResultsFiles: iglint-junit.xml
  • JUnit XML (--output-format junit) works with Jenkins, TeamCity, Bitbucket Pipelines, CircleCI and most others: one test case per finding, grouped by file.
  • SARIF (--output-format sarif) is read by many code scanning and review tools.
  • JSON and JSON lines (json, json-lines) are for your own scripts and dashboards.

iglint caches results in .iglint_cache in the project root. In CI a cold run is already fast (about 0.16 s on a 500-view synthetic corpus, 0.6 s on 2 CPUs), so caching across jobs is rarely worth it. Either keep the directory between runs with your CI's cache feature, or pass --no-cache to avoid writing it.

iglint can lint a list of files (iglint check path/a.py path/b/view.json), and still analyses the whole workspace around them, so cross-resource rules see the full project. For pull request gates, linting everything is usually simpler and still fast; per-file runs are what the pre-commit hook does.