CI/CD Integration
vigil is designed to integrate easily into CI/CD pipelines. Its deterministic exit codes, multiple output formats, and offline mode make it ideal for automation.
Exit codes
| Code | Meaning |
|---|---|
0 | No findings above the threshold |
1 | Findings found above the threshold |
2 | Execution error |
The threshold is configured with --fail-on (default: high).
GitHub Actions
Basic scan
name: vigil Security Scan
on:
push:
branches: [main]
pull_request:
jobs:
vigil:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install vigil
run: pip install vigil-ai-cli
- name: Run vigil
run: vigil scan src/ --fail-on high
With SARIF report (GitHub Code Scanning)
name: vigil SARIF
on:
push:
branches: [main]
pull_request:
jobs:
vigil:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install vigil
run: pip install vigil-ai-cli
- name: Run vigil
run: vigil scan src/ -f sarif -o vigil.sarif
continue-on-error: true
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: vigil.sarif
Findings appear in the Security > Code scanning alerts tab of the repository.
With dependency cache
- name: Cache vigil registry
uses: actions/cache@v4
with:
path: ~/.cache/vigil/registry/
key: vigil-registry-${{ hashFiles('**/requirements*.txt', '**/package.json') }}
restore-keys: |
vigil-registry-
Changed files only in PR
- name: Run vigil on changed files
run: vigil scan --changed-only --fail-on high
Recommended complete workflow
name: vigil
on:
push:
branches: [main, develop]
pull_request:
jobs:
security-scan:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Cache pip
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: pip-vigil-${{ hashFiles('pyproject.toml') }}
- name: Cache vigil registry
uses: actions/cache@v4
with:
path: ~/.cache/vigil/registry/
key: vigil-registry-${{ hashFiles('**/requirements*.txt', '**/package.json') }}
restore-keys: vigil-registry-
- name: Install vigil
run: pip install vigil-ai-cli
- name: Security scan
run: vigil scan src/ -f sarif -o vigil.sarif --fail-on high
continue-on-error: true
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: vigil.sarif
- name: Check exit code
run: vigil scan src/ --fail-on high --quiet
GitLab CI
Basic scan
vigil:
image: python:3.12-slim
stage: test
script:
- pip install vigil-ai-cli
- vigil scan src/ --fail-on high
With JUnit report
vigil:
image: python:3.12-slim
stage: test
script:
- pip install vigil-ai-cli
- vigil scan src/ -f junit -o report.xml --fail-on high
artifacts:
reports:
junit: report.xml
when: always
Findings appear in the merge request as failed tests in the Tests tab.
With JSON report as artifact
vigil:
image: python:3.12-slim
stage: test
script:
- pip install vigil-ai-cli
- vigil scan src/ -f json -o vigil-report.json
artifacts:
paths:
- vigil-report.json
when: always
allow_failure:
exit_codes:
- 1
Complete pipeline
stages:
- test
vigil-full:
image: python:3.12-slim
stage: test
script:
- pip install vigil-ai-cli
- vigil scan src/ -f junit -o report.xml
- vigil scan src/ -f json -o report.json
artifacts:
reports:
junit: report.xml
paths:
- report.json
when: always
cache:
key: vigil-registry
paths:
- ~/.cache/vigil/registry/
Azure DevOps
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.12'
- script: pip install vigil-ai-cli
displayName: 'Install vigil'
- script: vigil scan src/ -f junit -o $(Build.ArtifactStagingDirectory)/vigil-report.xml
displayName: 'Run vigil'
continueOnError: true
- task: PublishTestResults@2
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: '**/vigil-report.xml'
condition: always()
Pre-commit hooks
With pre-commit framework
Create or edit .pre-commit-config.yaml:
repos:
- repo: local
hooks:
- id: vigil
name: vigil security scan
entry: vigil scan --changed-only --fail-on high --quiet
language: python
additional_dependencies: ['vigil-ai-cli']
always_run: true
pass_filenames: false
Install:
pip install pre-commit
pre-commit install
Now vigil runs automatically before each commit, scanning only the changed files.
Manual git hook
Create .git/hooks/pre-commit:
#!/bin/bash
set -e
# Solo escanear archivos cambiados para rapidez
vigil scan --changed-only --fail-on high --quiet
if [ $? -eq 1 ]; then
echo ""
echo "vigil encontro problemas de seguridad. Corrige antes de hacer commit."
echo "Ejecuta 'vigil scan --changed-only' para ver los detalles."
exit 1
fi
chmod +x .git/hooks/pre-commit
Pre-commit recommendations
- Use
--changed-onlyso the scan is fast (only staged files). - Use
--quietto reduce output in the normal flow. - Use
--offlineif you do not want the hook to depend on internet connectivity. - Configure
--fail-on criticalif the full scan is too strict for the local development flow.
Quality gates
Per-environment strategy
# Desarrollo local (pre-commit): solo bloquear criticos
vigil scan --changed-only --fail-on critical --quiet
# PR / merge request: bloquear high y superiores
vigil scan src/ --fail-on high
# Release / produccion: bloquear desde medium
vigil scan src/ --fail-on medium --config .vigil.strict.yaml
With dedicated config files
proyecto/
.vigil.yaml # Config por defecto (standard)
.vigil.strict.yaml # Config para CI de produccion
.vigil.dev.yaml # Config para desarrollo local
# CI
vigil scan src/ --config .vigil.strict.yaml
# Local
vigil scan src/ --config .vigil.dev.yaml
Progressive fail-on
An effective strategy is to start relaxed and gradually increase the strictness:
- Week 1:
--fail-on critical— only block hallucinated dependencies and critical secrets. - Week 2:
--fail-on high— add unprotected endpoints, open CORS. - Week 3:
--fail-on medium— add insecure cookies, trivial tests.
This prevents vigil from blocking the team when it is first introduced.
Offline mode
In environments without internet access (isolated runners, air-gapped environments):
vigil scan src/ --offline
In offline mode, vigil:
- Does not make HTTP requests to PyPI or npm.
- Runs all static checks that do not require network access.
- Does run: DEP-003 (typosquatting by name similarity — does not require network).
- Does not run: DEP-001 (nonexistent package), DEP-002 (new package), DEP-005 (no source repo), DEP-007 (nonexistent version).
- Future analyzers (auth, secrets, tests) will be fully static and will work in offline mode.
This is useful in:
- CI runners without internet access.
- Corporate environments with restrictive proxies.
- Runs where speed is critical (no network latency).
Integration with other tools
With tox
# tox.ini
[testenv:security]
deps = vigil-ai-cli
commands = vigil scan src/ --fail-on high
With Makefile
.PHONY: security
security:
vigil scan src/ --fail-on high
.PHONY: security-report
security-report:
vigil scan src/ -f json -o reports/vigil.json
vigil scan src/ -f sarif -o reports/vigil.sarif
With nox (Python)
# noxfile.py
import nox
@nox.session
def security(session):
session.install("vigil-ai-cli")
session.run("vigil", "scan", "src/", "--fail-on", "high")