Integrate CI and Dependency-Track¶
This document explains how to enable and configure the two quality/security features of gitrust:
- The integrated CI (Dagger) which executes the builds/tests/lints on each push.
- The dependency tracker (Syft + Dependency-Track) which scans code components with each push and detects known vulnerabilities.
These two systems are independent: one can be activated without the other.
1. General architecture¶
flowchart TB
subgraph Client
Dev[Développeur]
end
subgraph Gitrust[Instance Gitrust]
HTTP[:4000 HTTP/Git]
SSH[:2222 SSH/Git]
Worker[CiWorker
tokio task]
Sbom[SbomService
tokio spawn]
DB[(PostgreSQL)]
end
subgraph Builder[Serveur de build]
Docker[Docker/Podman]
Dagger[Dagger CLI]
CiEngine[/opt/gitrust-ci/ci-engine/]
end
subgraph Security[Stack sécurité optionnelle]
Syft[syft]
Dtrack[Dependency-Track]
end
Dev -->|git push| HTTP
Dev -->|git push| SSH
HTTP --> Worker
SSH --> Worker
HTTP --> Sbom
SSH --> Sbom
Worker -->|SSH + rsync| Builder
Builder -->|logs streamés| Worker
Worker --> DB
Sbom -->|scan workspace| Syft
Sbom -->|PUT BOM| Dtrack
Dtrack -->|findings| Sbom
Sbom --> DB
Three components operate in parallel:
- CiWorker: Tokio task which consumes
CiTaskfrom anmpscchannel, limited by aSemaphoretoCI_MAX_CONCURRENTsimultaneous pipelines. - SbomService: executed in a
tokio::spawnafter each push, totally decoupled from the CI. - Build server: remote machine (or
localhost) that runs Docker + Dagger. Gitrust sends the workspace there by rsync and launches Dagger by SSH.
2. Set up the CI¶
2.1 Build server prerequisites¶
The build server can be the same machine as Gitrust (CI_REMOTE_HOST=localhost) or a dedicated machine. He must have:
| Outil | Rôle |
|---|---|
| Docker ou Podman | Containers Dagger |
| Dagger CLI | Moteur d'exécution |
| SSH (accès sortant depuis Gitrust) | Transport |
| rsync | Copie du workspace |
| git, tar | Extraction du tree du commit |
Recommended automatic installation:
# Depuis la machine Gitrust (l'utilisateur doit pouvoir SSH vers le builder)
./deployment/setup-remote-ci.sh .env
The script executes:
- Checking SSH connectivity
- Installing Docker if absent
- Installing Dagger CLI if absent
- Creating the remote working directory
- Synchronization of the
ci-engine - Smoke test (versions)
2.2 Gitrust configuration (.env file)¶
Add to Gitrust's .env:
# Activer globalement le CI
CI_ENABLED=true
# Chemin du ci-engine sur le serveur de build
CI_ENGINE_PATH=/opt/gitrust-ci/ci-engine
# Limite de parallélisme
CI_MAX_CONCURRENT=4
CI_DEFAULT_TIMEOUT=3600
CI_WORKSPACE_PATH=/tmp/gitrust-ci
# Serveur de build (mettre localhost pour "même machine")
CI_REMOTE_HOST=builder.example.com
CI_REMOTE_USER=ci-runner
CI_REMOTE_PATH=/opt/gitrust-ci
CI_REMOTE_SSH_PORT=22
# CI_REMOTE_SSH_KEY=/home/gitrust/.ssh/id_ed25519 # si pas ssh-agent
Restart Gitrust: systemctl restart gitrust (or cargo run --release).
2.3 Activate CI on a repository¶
In the web interface: go to the repository → Settings → CI.
- Check CI enabled (required — default
false) - Check Trigger on push (activates execution on each push)
- Optional: Auto-cancel (cancels current pipelines when a new one starts)
- Optional: Allowed branches (e.g.
main,develop— empty = all)
2.4 Choose mode: Easy or Power¶
flowchart LR
Push[Commit
poussé] --> Tree{Arbre du
commit contient ?}
Tree -->|.dagger/| Power[Mode Power
dagger call -m .dagger/ ci]
Tree -->|.gitrust-ci.yml| Easy[Mode Easy
dagger call -m ci-engine test-pr]
Tree -->|rien| None[Pas de pipeline]
Power --> Run[Exécution
distante SSH]
Easy --> Run
Easy mode (recommended to start)¶
Create .gitrust-ci.yml at the root of the repository:
# Raccourci : charge un profil pré-configuré (rust | python | node)
language: rust
build:
command: "cargo build --release"
checks:
lint: "cargo clippy -- -D warnings"
format: "cargo fmt -- --check"
tests:
command: "cargo test --release"
The available profiles are located in deployment/ci-engine/profiles/ (rust.yaml, python.yaml, node.yaml) in the source repository.
Power mode¶
For advanced users, create a complete Dagger module in .dagger/:
The ci function of the module is called directly:
Advantage: access to the Daggerverse, composition, pipeline testing. See the Dagger documentation.
2.5 Monitoring a pipeline¶
After a git push, an entry appears in the CI tab of the repository:
stateDiagram-v2
[*] --> Pending: create_pipeline
Pending --> Running: worker picks CiTask
Running --> Success: exit 0
Running --> Failure: exit != 0
Running --> Cancelled: timeout / auto_cancel / manuel
Success --> [*]
Failure --> [*]
Cancelled --> [*]
The stdout/stderr logs are streamed line by line in the ci_logs table and visible live in the UI. If it fails, a notification is sent to the repository owner.
3. Set up the Dependency Tracker¶
This part is completely independent of the CI. It scans the pushed code and produces a CycloneDX SBOM, then (optionally) sends it to Dependency-Track for vulnerability scanning.
3.1 Install Syft¶
On the Gitrust machine (the scan is done locally, not on the builder):
# Installation officielle
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh \
| sh -s -- -b /usr/local/bin
# Vérification
syft --version
In .env:
At this stage: with each push, a CycloneDX SBOM is generated and stored (without external upload). Visible in the Security tab of the repository: number of components, sha256 of the BOM.
3.2 Deploy Dependency-Track¶
Dependency-Track is a Java application that stores SBOM and correlates with CVE/OSV/NVD databases. Recommended Docker deployment:
mkdir -p /opt/dtrack && cd /opt/dtrack
curl -L -o docker-compose.yml \
https://dependencytrack.org/docker-compose.yml
docker compose up -d
L'API est disponible sur http://localhost:8081 et l'UI sur http://localhost:8080.
Login initial : admin / admin (à changer immédiatement).
3.3 Create an API key¶
In Dependency-Track → Administration → Access Management → Teams:
- Create (or reuse) a
gitrustteam. - Give it permissions:
BOM_UPLOADPROJECT_CREATION_UPLOADVIEW_PORTFOLIOVIEW_VULNERABILITY- Generate an API key and copy it.
3.4 Configure Gitrust¶
Add to .env:
CI_DTRACK_ENABLED=true
CI_DTRACK_URL=http://localhost:8081
CI_DTRACK_API_KEY=odt_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Restart Gitrust. With each push:
sequenceDiagram
participant Push as post-receive
participant Sbom as SbomService
participant Git as git archive
participant Syft
participant Dtrack as Dependency-Track
participant DB as sbom_reports
Push->>Sbom: process_push(sha, ref)
Sbom->>DB: upsert status=pending
Sbom->>Git: archive sha | tar -x tmpdir
Sbom->>Syft: scan dir:tmpdir -o cyclonedx-json
Syft-->>Sbom: BOM bytes
Sbom->>DB: update sha256
Sbom->>Dtrack: PUT /api/v1/bom (base64)
Dtrack-->>Sbom: token
loop max 30s
Sbom->>Dtrack: GET /api/v1/bom/token/{token}
Dtrack-->>Sbom: processing ?
end
Sbom->>Dtrack: GET /api/v1/finding/project/{uuid}
Dtrack-->>Sbom: findings[]
Sbom->>DB: update status=success
+ critical/high/medium/low
3.5 Read the results¶
Security tab of the repository → SBOM insert:
- Number of components detected
- Counters by severity: Critical / High / Medium / Low
- Direct link to project in Dependency-Track (if UUID is resolved)
- Hash sha256 from BOM (traceability)
If Dependency-Track takes more than 30s to analyze, the status remains processing — a subsequent sweeper will search for the findings.
4. Debugging¶
Common CI Problems¶
| Symptôme | Cause probable | Vérifier |
|---|---|---|
Pipeline reste pending |
Worker non démarré, ou channel saturé | Logs CI worker started, CI_MAX_CONCURRENT |
Échec rsync vers le serveur de build |
SSH bloqué, clé absente | ssh -p ${CI_REMOTE_SSH_PORT} ${CI_REMOTE_USER}@${CI_REMOTE_HOST} manuel |
dagger: command not found |
Dagger non installé sur le builder | Relancer setup-remote-ci.sh |
Status Cancelled inattendu |
Timeout (CI_DEFAULT_TIMEOUT) ou auto-cancel |
Augmenter le timeout, vérifier pipelines concurrents |
Common SBOM Issues¶
| Symptôme | Cause probable | Vérifier |
|---|---|---|
SBOM generation disabled |
CI_SBOM_ENABLED=false |
.env |
syft spawn failed |
Binaire introuvable | which syft, CI_SYFT_BIN |
invalid commit sha |
SHA non hex 40 chars | Rare, signale un bug |
Dtrack upload 401 |
API key invalide ou permissions manquantes | Régénérer, vérifier les 4 permissions |
Status processing indéfiniment |
Dtrack surchargé, analyse lente | Attendre, ou relancer un push |
Useful logs¶
# Logs Gitrust (systemd)
journalctl -u gitrust -f | grep -E "CI|SBOM|sbom|pipeline"
# Vérifier un pipeline en DB
psql $DATABASE_URL -c "SELECT id, status, commit_sha, created_at FROM ci_pipelines ORDER BY created_at DESC LIMIT 10;"
# Vérifier un SBOM
psql $DATABASE_URL -c "SELECT commit_sha, status, components_count, critical_count, high_count FROM sbom_reports ORDER BY created_at DESC LIMIT 10;"
5. Summary checklist¶
CI :
- [ ] Docker + Dagger installés sur le serveur de build (setup-remote-ci.sh)
- [ ] CI_ENABLED=true et CI_REMOTE_* dans .env
- [ ] Gitrust redémarré
- [ ] CI activée dans Settings → CI pour chaque dépôt
- [ ] Fichier .gitrust-ci.yml (Easy) ou .dagger/ (Power) commité
- [ ] Push → pipeline visible dans l'onglet CI
Dependency Tracker :
- [ ] Syft installé sur la machine Gitrust
- [ ] CI_SBOM_ENABLED=true dans .env
- [ ] (Optionnel) Dependency-Track déployé + API key créée avec les 4 permissions
- [ ] (Optionnel) CI_DTRACK_ENABLED=true, CI_DTRACK_URL, CI_DTRACK_API_KEY dans .env
- [ ] Gitrust redémarré
- [ ] Push → SBOM visible dans l'onglet Security