Skip to content

CI/CD Integration

The --ci flag turns SiteOne Crawler into a quality gate for your pipeline. After crawling completes, the crawler evaluates a set of configurable thresholds against the quality score, error counts, and crawl-coverage metrics. If any threshold is not met, the crawler exits with code 10 โ€” distinct from exit code 1 for runtime errors โ€” so your pipeline can block a deployment automatically.

In CI mode, the default file outputs (HTML, JSON, TXT reports) are automatically suppressed โ€” only the console output and the exit code matter. If you need report files in CI, request them explicitly, e.g.:

Terminal window
./siteone-crawler --url=https://staging.example.com --ci --output-html-report=report.html

Bonus โ€” cache warming. Running the crawler as a post-deployment step crawls every page and asset on your site, which populates the HTML/asset cache on your reverse proxy (Varnish, Nginx) or CDN (Cloudflare, CloudFront). The first real visitors then hit a warm cache instead of cold origin requests.

CodeMeaning
0Success (with --ci this also means all quality thresholds passed)
1Runtime error
2Help/version displayed
3No pages crawled (e.g. DNS failure, timeout, connection refused)
10CI/CD quality gate failed
101Configuration error

All thresholds are opt-in via the --ci-* flags below. The defaults shown are the values applied when --ci is enabled. Where no default is listed, the metric is not checked unless you set it.

OptionDefaultMeaning
--cioffEnable the CI/CD quality gate. Exits with code 10 if thresholds are not met.
--ci-min-score=<val>5.0Minimum overall quality score (0.0-10.0).
--ci-min-performance=<val>5Minimum Performance category score (0.0-10.0).
--ci-min-seo=<val>5Minimum SEO category score (0.0-10.0).
--ci-min-security=<val>5Minimum Security category score (0.0-10.0).
--ci-min-accessibility=<val>3Minimum Accessibility category score (0.0-10.0).
--ci-min-best-practices=<val>5Minimum Best Practices category score (0.0-10.0).
--ci-max-404=<int>0Maximum number of 404 responses allowed.
--ci-max-5xx=<int>0Maximum number of 5xx server error responses allowed.
--ci-max-criticals=<int>0Maximum number of critical analysis findings allowed.
--ci-max-warnings=<int>not checkedMaximum number of warning analysis findings allowed.
--ci-max-avg-response=<val>not checkedMaximum average response time in seconds.
--ci-min-pages=<int>10Minimum number of HTML pages that must be found.
--ci-min-assets=<int>10Minimum number of assets (JS, CSS, images, fonts) that must be found.
--ci-min-documents=<int>0Minimum number of documents (PDF, etc.) that must be found.
--ci-baseline=<file>not setPath to a previous JSON output used as a baseline for regression checks.
--ci-max-score-drop=<val>0Maximum allowed drop of the overall score vs the --ci-baseline run (0 = any drop fails).
--ci-fail-on-code=<val>not setFail the build if a finding code (aplCode, e.g. seo-noindex-sitewide) is present. Repeatable.
--ci-ignore-code=<val>not setIgnore a finding code (aplCode, e.g. pages-without-lang) when counting criticals/warnings (also suppresses --ci-fail-on-code). Repeatable.
--ci-junit-file=<file>not setWrite the CI gate result as a JUnit XML report to this file.
--ci-github-annotationsoffPrint GitHub Actions error annotations for failed CI checks (auto-enabled when GITHUB_ACTIONS=true).

The --ci-min-* thresholds map directly onto the five categories of the quality score.

--ci-junit-file=<file> writes the quality-gate result as a JUnit XML report. JUnit is the de-facto standard test-report format, so the file renders natively in the test reporters of GitLab, Jenkins, and GitHub โ€” each failed check shows up as a failed test case with its metric, operator, threshold, and actual value.

Terminal window
./siteone-crawler --url=https://staging.example.com --ci --ci-junit-file=crawler-junit.xml

--ci-github-annotations prints GitHub Actions ::error annotations for each failed check, so the failures appear inline in the pull request diff/checks view. It is auto-enabled when GITHUB_ACTIONS=true, so under GitHub Actions you usually donโ€™t need to pass it explicitly.

Instead of (or in addition to) absolute floors, you can gate on regressions โ€” failing only when the overall score drops compared with a previous run:

  • --ci-baseline=<file> points to a previous JSON output to use as the baseline.
  • --ci-max-score-drop=<val> sets the maximum allowed drop of the overall score versus that baseline. The default is 0, meaning any drop fails the build.

Keep a baseline JSON from the previous run, then compare the current crawl against it:

- name: Check for quality regressions
run: |
./siteone-crawler --url=https://staging.example.com --ci \
--ci-baseline=baseline.json --ci-max-score-drop=0.3 \
--output-json-file=current.json

Every analysis finding has a stable code (aplCode). You can target individual findings rather than aggregate counts:

  • --ci-fail-on-code=<code> fails the build when a specific finding is present, e.g. --ci-fail-on-code=seo-noindex-sitewide to block a deploy that would accidentally noindex the whole site.
  • --ci-ignore-code=<code> excludes a finding from the criticals/warnings counts (and suppresses --ci-fail-on-code for it), e.g. --ci-ignore-code=pages-without-lang to tolerate a known, accepted issue.

Both flags are repeatable.

When --ci is enabled, a quality-gate box is displayed after the quality scores:

โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
โ•‘ CI/CD QUALITY GATE โ•‘
โ• โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฃ
โ•‘ [PASS] Overall score: 7.2 >= 5 โ•‘
โ•‘ [PASS] 404 errors: 0 <= 0 โ•‘
โ•‘ [PASS] 5xx errors: 0 <= 0 โ•‘
โ•‘ [FAIL] Critical findings: 2 > 0 (max: 0) โ•‘
โ• โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฃ
โ•‘ RESULT: FAIL (1 of 4 checks failed) โ€” exit code 10 โ•‘
โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

With --output=json --ci, the JSON includes a ciGate object describing every evaluated check:

{
"ciGate": {
"passed": false,
"exitCode": 10,
"checks": [
{"metric": "Overall score", "operator": ">=", "threshold": 5.0, "actual": 7.2, "passed": true},
{"metric": "404 errors", "operator": "<=", "threshold": 0.0, "actual": 0.0, "passed": true},
{"metric": "Critical findings", "operator": "<=", "threshold": 0.0, "actual": 2.0, "passed": false}
]
}
}
- name: Check website quality
run: |
./siteone-crawler \
--url=https://staging.example.com \
--ci \
--ci-min-score=7.0 \
--ci-min-security=8.0 \
--ci-max-404=0 \
--ci-max-5xx=0 \
--ci-junit-file=crawler-junit.xml \
--ci-github-annotations

--ci-github-annotations surfaces each failed check inline in the PR (and is auto-enabled under GITHUB_ACTIONS=true), while --ci-junit-file produces a JUnit report you can upload with a test-reporter action.

quality_check:
script:
- ./siteone-crawler --url=$STAGING_URL --ci --ci-min-score=6.0
allow_failure: false

The JUnit report from --ci-junit-file can be wired into GitLabโ€™s artifacts:reports:junit so failed checks appear in the merge-request widget.