2026-04-08 20:00:14 -03:00
pipeline {
2026-04-12 05:59:13 -03:00
agent {
kubernetes {
label 'lesavka-tests'
defaultContainer 'rust-ci'
yaml """
apiVersion: v1
kind: Pod
spec:
nodeSelector:
kubernetes.io/arch: arm64
node-role.kubernetes.io/worker: "true"
containers:
- name: rust-ci
2026-04-23 10:35:10 -03:00
image: rust:1.88-bookworm
2026-04-12 05:59:13 -03:00
command: ["cat"]
tty: true
volumeMounts:
- name: workspace-volume
mountPath: /home/jenkins/agent
volumes:
- name: workspace-volume
emptyDir: {}
"""
}
}
2026-04-08 20:00:14 -03:00
options {
disableConcurrentBuilds()
2026-04-12 05:43:32 -03:00
disableResume()
2026-04-08 20:00:14 -03:00
}
parameters {
2026-04-12 05:18:42 -03:00
booleanParam(name: 'PUSH_IMAGES', defaultValue: false, description: 'Push images to registry (enable for release runs)')
2026-05-10 23:14:15 -03:00
choice(name: 'LESAVKA_CI_PROFILE', choices: ['safe', 'daily', 'lab'], description: 'Safe is the normal non-disruptive gate; daily is intended for scheduled master/main runs; lab enables explicitly configured bare-metal probes.')
booleanParam(name: 'RUN_DISRUPTIVE_INPUT_TESTS', defaultValue: false, description: 'Run virtual HID tests only on an isolated worker/session; these can emit keyboard/mouse events.')
booleanParam(name: 'RUN_LAB_HARDWARE_GATES', defaultValue: false, description: 'Run opt-in bare-metal lab gates for Theia/Tethys/RCT probes when the Jenkins worker is prepared for them.')
2026-04-10 16:38:41 -03:00
string(name: 'QUALITY_GATE_PUSHGATEWAY_URL', defaultValue: 'http://platform-quality-gateway.monitoring.svc.cluster.local:9091', description: 'Pushgateway base URL for quality gate metrics')
2026-04-08 20:00:14 -03:00
string(name: 'REGISTRY_CREDENTIALS_ID', defaultValue: 'registry-bstein-dev', description: 'Jenkins credentials id for registry.bstein.dev')
}
environment {
REGISTRY = 'registry.bstein.dev'
IMAGE_PREFIX = "${REGISTRY}/lesavka"
CARGO_TERM_COLOR = 'always'
DOCKER_BUILDKIT = '1'
2026-05-10 23:14:15 -03:00
LESAVKA_CI_PROFILE = "${params.LESAVKA_CI_PROFILE}"
2026-04-08 20:00:14 -03:00
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
2026-04-12 05:59:13 -03:00
stage('Bootstrap CI Toolchain') {
steps {
container('rust-ci') {
sh '''
set -eu
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
python3 \
curl \
2026-04-23 01:13:29 -03:00
file \
2026-04-12 05:59:13 -03:00
clang \
llvm \
pkg-config \
libssl-dev \
2026-04-12 06:29:14 -03:00
ca-certificates \
2026-04-12 06:27:26 -03:00
libgstreamer1.0-dev \
2026-04-12 06:36:19 -03:00
libgstreamer-plugins-base1.0-dev \
2026-04-12 06:44:41 -03:00
protobuf-compiler \
2026-04-12 06:44:14 -03:00
libpango1.0-dev \
libcairo2-dev \
2026-04-12 06:59:13 -03:00
libgdk-pixbuf-2.0-dev \
2026-04-12 06:58:56 -03:00
libgtk-4-dev
2026-04-12 05:59:13 -03:00
rm -rf /var/lib/apt/lists/*
2026-04-12 06:22:15 -03:00
rustup component add rustfmt llvm-tools-preview clippy
2026-04-12 10:05:51 -03:00
git config --global --add safe.directory "$WORKSPACE"
2026-04-12 05:59:13 -03:00
if ! cargo llvm-cov --version >/dev/null 2>&1; then
cargo install --locked cargo-llvm-cov
fi
'''
}
}
}
2026-05-10 23:14:15 -03:00
stage('Daily Master Gate') {
when {
expression { return params.LESAVKA_CI_PROFILE == 'daily' }
}
steps {
container('rust-ci') {
sh 'QUALITY_GATE_PUSHGATEWAY_URL="${QUALITY_GATE_PUSHGATEWAY_URL}" scripts/ci/daily_master_gate.sh'
}
}
}
2026-04-23 01:13:29 -03:00
stage('Style Docs LOC Naming') {
2026-05-10 23:14:15 -03:00
when {
expression { return params.LESAVKA_CI_PROFILE != 'daily' }
}
2026-04-08 20:00:14 -03:00
steps {
2026-04-12 05:59:13 -03:00
container('rust-ci') {
2026-04-23 01:13:29 -03:00
sh 'scripts/ci/hygiene_gate.sh'
2026-04-12 05:59:13 -03:00
}
2026-04-08 20:00:14 -03:00
}
}
2026-04-23 01:13:29 -03:00
stage('Coverage') {
2026-05-10 23:14:15 -03:00
when {
expression { return params.LESAVKA_CI_PROFILE != 'daily' }
}
2026-04-08 20:00:14 -03:00
steps {
2026-04-12 05:59:13 -03:00
container('rust-ci') {
2026-04-23 01:13:29 -03:00
sh 'QUALITY_GATE_PUSHGATEWAY_URL="${QUALITY_GATE_PUSHGATEWAY_URL}" scripts/ci/quality_gate.sh'
2026-04-12 05:59:13 -03:00
}
2026-04-08 20:00:14 -03:00
}
}
2026-04-23 01:13:29 -03:00
stage('Tests') {
2026-05-10 23:14:15 -03:00
when {
expression { return params.LESAVKA_CI_PROFILE != 'daily' }
}
2026-04-10 17:00:33 -03:00
steps {
2026-04-12 05:59:13 -03:00
container('rust-ci') {
2026-04-21 21:38:22 -03:00
sh 'QUALITY_GATE_PUSHGATEWAY_URL="${QUALITY_GATE_PUSHGATEWAY_URL}" scripts/ci/test_gate.sh'
2026-04-12 05:59:13 -03:00
}
2026-04-10 17:00:33 -03:00
}
}
2026-05-10 23:14:15 -03:00
stage('Performance') {
when {
expression { return params.LESAVKA_CI_PROFILE != 'daily' }
}
steps {
container('rust-ci') {
sh 'QUALITY_GATE_PUSHGATEWAY_URL="${QUALITY_GATE_PUSHGATEWAY_URL}" scripts/ci/performance_gate.sh'
}
}
}
2026-04-23 01:13:29 -03:00
stage('Media Reliability') {
2026-05-10 23:14:15 -03:00
when {
expression { return params.LESAVKA_CI_PROFILE != 'daily' }
}
2026-04-08 20:00:14 -03:00
steps {
2026-04-12 05:59:13 -03:00
container('rust-ci') {
2026-04-23 01:13:29 -03:00
sh 'QUALITY_GATE_PUSHGATEWAY_URL="${QUALITY_GATE_PUSHGATEWAY_URL}" scripts/ci/media_reliability_gate.sh'
2026-04-21 21:38:22 -03:00
}
}
}
2026-05-10 23:14:15 -03:00
stage('Input Transport (Isolated Opt-In)') {
when {
expression { return params.RUN_DISRUPTIVE_INPUT_TESTS }
}
steps {
container('rust-ci') {
sh 'QUALITY_GATE_PUSHGATEWAY_URL="${QUALITY_GATE_PUSHGATEWAY_URL}" LESAVKA_ALLOW_DISRUPTIVE_INPUT_TESTS=1 scripts/ci/input_transport_gate.sh'
}
}
}
stage('Bare-Metal Lab Gates (Opt-In)') {
when {
expression { return params.RUN_LAB_HARDWARE_GATES || params.LESAVKA_CI_PROFILE == 'lab' }
}
steps {
container('rust-ci') {
sh 'QUALITY_GATE_PUSHGATEWAY_URL="${QUALITY_GATE_PUSHGATEWAY_URL}" LESAVKA_ALLOW_LAB_HARDWARE_TESTS=1 scripts/ci/baremetal_lab_gate.sh'
}
}
}
2026-04-23 01:13:29 -03:00
stage('Gate Glue') {
2026-05-10 23:14:15 -03:00
when {
expression { return params.LESAVKA_CI_PROFILE != 'daily' }
}
2026-04-21 21:38:22 -03:00
steps {
container('rust-ci') {
2026-04-23 01:13:29 -03:00
sh 'QUALITY_GATE_PUSHGATEWAY_URL="${QUALITY_GATE_PUSHGATEWAY_URL}" scripts/ci/gate_glue_gate.sh'
2026-04-21 21:38:22 -03:00
}
}
}
2026-04-23 01:13:29 -03:00
stage('SonarQube') {
2026-05-10 23:14:15 -03:00
when {
expression { return params.LESAVKA_CI_PROFILE != 'daily' }
}
2026-04-21 21:38:22 -03:00
steps {
container('rust-ci') {
2026-04-23 01:13:29 -03:00
sh 'QUALITY_GATE_PUSHGATEWAY_URL="${QUALITY_GATE_PUSHGATEWAY_URL}" scripts/ci/sonarqube_gate.sh'
2026-04-12 05:59:13 -03:00
}
2026-04-08 20:00:14 -03:00
}
}
2026-04-10 15:56:18 -03:00
stage('Build Dist') {
2026-05-10 23:14:15 -03:00
when {
expression { return params.LESAVKA_CI_PROFILE != 'daily' }
}
2026-04-08 20:00:14 -03:00
steps {
2026-04-12 05:59:13 -03:00
container('rust-ci') {
sh 'scripts/ci/build-dist.sh'
}
2026-04-08 20:00:14 -03:00
}
}
2026-04-23 01:13:29 -03:00
stage('Supply Chain Artifact Security') {
2026-05-10 23:14:15 -03:00
when {
expression { return params.LESAVKA_CI_PROFILE != 'daily' }
}
2026-04-23 01:13:29 -03:00
steps {
container('rust-ci') {
sh 'QUALITY_GATE_PUSHGATEWAY_URL="${QUALITY_GATE_PUSHGATEWAY_URL}" scripts/ci/supply_chain_gate.sh'
}
}
}
2026-04-08 20:00:14 -03:00
stage('Docker Login') {
when {
2026-05-10 23:14:15 -03:00
expression { return params.LESAVKA_CI_PROFILE != 'daily' && params.PUSH_IMAGES }
2026-04-08 20:00:14 -03:00
}
steps {
withCredentials([
usernamePassword(
credentialsId: params.REGISTRY_CREDENTIALS_ID,
usernameVariable: 'REGISTRY_USER',
passwordVariable: 'REGISTRY_PASS'
)
]) {
sh 'echo "$REGISTRY_PASS" | docker login "$REGISTRY" -u "$REGISTRY_USER" --password-stdin'
}
}
}
stage('Build Images') {
2026-04-12 05:18:42 -03:00
when {
2026-05-10 23:14:15 -03:00
expression { return params.LESAVKA_CI_PROFILE != 'daily' && params.PUSH_IMAGES }
2026-04-12 05:18:42 -03:00
}
2026-04-08 20:00:14 -03:00
steps {
sh 'PUSH_IMAGES=${PUSH_IMAGES} scripts/ci/build-images.sh'
}
}
}
post {
always {
2026-04-12 05:25:43 -03:00
script {
try {
2026-05-10 23:14:15 -03:00
archiveArtifacts artifacts: 'dist/**,target/test-gate/**,target/quality-gate/**,target/hygiene-gate/**,target/daily-master-gate/**,target/performance-gate/**,target/media-reliability-gate/**,target/input-transport-gate/**,target/baremetal-lab-gate/**,target/video-downstream-gate/**,target/gate-glue-gate/**,target/sonarqube-gate/**,target/supply-chain-gate/**', fingerprint: true, allowEmptyArchive: true
2026-04-12 05:25:43 -03:00
} catch (Throwable err) {
echo "archive step unavailable: ${err.class.simpleName}"
}
2026-04-12 05:18:42 -03:00
}
2026-04-08 20:00:14 -03:00
}
}
}