Automating WCET as Code: IaC Templates for Timing Verification in Safety‑Critical Builds
Automate WCET as Code: Terraform + Ansible templates and CI snippets to run RocqStat/VectorCAST timing checks as gated merge policies in 2026.
Hook: Stop late-stage surprises — make WCET verification part of your gated merge
Safety‑critical teams still face the same costly problem in 2026: WCET regressions discovered after release candidates are built and integrated into hardware. The fix is not manual runs or ad‑hoc environments — it's WCET as Code. This article gives you production‑ready IaC templates and pipeline snippets (Terraform + Ansible + CI) to provision verification environments and run RocqStat / VectorCAST timing analyses automatically as part of gated merges.
Why this matters in 2026
Two trends accelerated in late 2025 and early 2026: regulators and OEMs demand stronger timing evidence for real‑time controllers, and tool consolidation is happening after Vector's acquisition of RocqStat (Jan 2026). Vector's roadmap is pushing unified timing and testing workflows, which makes integrating these checks into CI easier and more compelling.
Vector Informatik’s acquisition of RocqStat signals a move toward unified timing analysis and verification workflows across safety‑critical toolchains (Jan 2026).
High‑level architecture: ephemeral verification environments
Here’s the pattern we recommend:
- Ephemeral compute: spin up a single-purpose VM or container per merge request to ensure environment parity.
- Artifact retrieval: fetch the build artifact (ELF, map, object files) from CI artifact storage or an S3 bucket.
- License & secrets: inject licensing and credentials from a secrets manager (Vault, AWS SSM Parameter Store).
- Run timing analysis: execute RocqStat/VectorCAST CLI and capture WCET outputs.
- Policy check: parse output, compare against thresholds in repo (wcet.yaml), and set status for merge gating.
- Destroy: tear down ephemeral resources to save cost.
Core principles and best practices
- Idempotent IaC: Terraform state per branch/pipeline and deterministic teardown.
- Environment parity: run on the same OS, compiler and toolchain as target hardware (use container images or immutable AMIs).
- Short lived infra: auto‑destroy after run; use spot instances where appropriate for non‑blocking analysis.
- Secrets handling: never bake license keys into images; mount at runtime from Vault/SSM.
- Thresholds as code: store safe‑timing budgets and rules in repo and version them.
Terraform: provisioning an ephemeral AWS EC2 verification VM
The following Terraform snippet provisions an EC2 instance used to run RocqStat/VectorCAST jobs. It creates a minimal IAM role so the instance can fetch artifacts from S3 and retrieve secrets from SSM. Use a per‑pipeline workspace to isolate runs.
# terraform/main.tf
provider "aws" {
region = var.region
}
resource "aws_iam_role" "ec2_role" {
name = "wcet-verifier-${var.pipeline_id}"
assume_role_policy = data.aws_iam_policy_document.ec2_assume_role.json
}
data "aws_iam_policy_document" "ec2_assume_role" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}
resource "aws_iam_role_policy" "ec2_policy" {
name = "wcet-ec2-policy"
role = aws_iam_role.ec2_role.id
policy = jsonencode({
Version = "2012-10-17",
Statement = [
{ Action = ["s3:GetObject"], Resource = ["${var.artifact_bucket_arn}/*"], Effect = "Allow" },
{ Action = ["ssm:GetParameters", "ssm:GetParameter"], Resource = ["${var.ssm_prefix}*"], Effect = "Allow" },
{ Action = ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"], Resource = "*", Effect = "Allow" }
]
})
}
resource "aws_instance" "verifier" {
ami = var.ami_id
instance_type = var.instance_type
iam_instance_profile = aws_iam_instance_profile.ec2_profile.name
key_name = var.ssh_key
tags = { Name = "wcet-verifier-${var.pipeline_id}" }
user_data = file("cloud-init/verifier-userdata.sh")
}
resource "aws_iam_instance_profile" "ec2_profile" {
name = "wcet-verifier-profile-${var.pipeline_id}"
role = aws_iam_role.ec2_role.name
}
output "verifier_ip" {
value = aws_instance.verifier.public_ip
}
Notes
- Use a hardened AMI with your baseline toolchain preinstalled (GCC, cross‑toolchain, Python) to reduce setup time.
- Keep Terraform state isolated per pipeline (workspaces) or use short‑lived state files in remote storage.
Ansible: install and run RocqStat / VectorCAST on the VM
Use Ansible for repeatable configuration: fetch artifacts from S3, install or extract vendor tooling, run CLI analysis and upload artifacts. The playbook below assumes a license file pulled from SSM and a CLI installer accessible via an internal URL or S3.
# ansible/playbooks/run_wcet.yml
- hosts: verifier
become: yes
vars:
artifact_bucket: "{{ lookup('env','ARTIFACT_BUCKET') }}"
artifact_key: "{{ lookup('env','ARTIFACT_KEY') }}"
license_param: "/tools/rocqstat/license"
wcet_config: "wcet.yaml"
tasks:
- name: Ensure directories
file:
path: /opt/wcet
state: directory
mode: '0755'
- name: Fetch build artifact from S3
aws_s3:
bucket: "{{ artifact_bucket }}"
object: "{{ artifact_key }}"
dest: /opt/wcet/artifact.elf
mode: get
- name: Retrieve license from SSM
amazon.aws.aws_ssm_parameter_store:
name: "{{ license_param }}"
region: "{{ aws_region }}"
with_decryption: true
register: license
- name: Write license file
copy:
content: "{{ license.parameter.value }}"
dest: /opt/wcet/license.lic
mode: '0600'
- name: Install RocqStat/VectorCAST CLI
shell: |
set -e
if [ ! -d /opt/vectorcast ]; then
mkdir -p /opt/vectorcast
# placeholder: download and extract vendor installer
aws s3 cp s3://{{ installer_bucket }}/vectorcast-cli.tar.gz - | tar xz -C /opt/vectorcast
fi
args:
warn: false
- name: Run timing analysis CLI
shell: |
set -e
export LC_ALL=C
export VCAST_LICENSE_FILE=/opt/wcet/license.lic
/opt/vectorcast/bin/vectorcast_cli --wcet-analyze --input /opt/wcet/artifact.elf --output /opt/wcet/results.json
register: wcet_run
ignore_errors: false
- name: Upload results to S3
aws_s3:
bucket: "{{ result_bucket }}"
object: "results/{{ lookup('env','PIPELINE_ID') }}-results.json"
src: /opt/wcet/results.json
mode: put
Parsing and pass/fail policy
Vendor tools typically emit JSON or XML outputs containing WCET numbers per function. Add a simple parser that compares the worst‑case value with wcet.yaml thresholds in the repository and returns a non‑zero exit code on failure. That non‑zero exit code signals CI to mark the job failed and block merge.
# tools/parse_wcet.py
import json, sys, yaml
with open('results.json') as f:
r = json.load(f)
with open('wcet.yaml') as f:
cfg = yaml.safe_load(f)
# simple example — vendor output may differ
max_wcet = max([fn['wcet_us'] for fn in r['functions']])
policy_limit = cfg['global_wcet_us']
print(f"max_wcet={max_wcet}us limit={policy_limit}us")
if max_wcet > policy_limit:
print('WCET policy violation')
sys.exit(2)
sys.exit(0)
GitLab CI pipeline: orchestrate terraform + ansible + policy check
Below is a GitLab CI minimal pipeline. It creates the environment, runs Ansible against the new verifier VM via SSH, fetches results and tears down the infra. The pipeline uses a per‑pipeline Terraform workspace and destroys infra at the end.
# .gitlab-ci.yml
stages:
- provision
- analyze
- cleanup
provision:
stage: provision
image: hashicorp/terraform:1.5
script:
- terraform init
- terraform workspace new ${CI_PIPELINE_ID} || terraform workspace select ${CI_PIPELINE_ID}
- terraform apply -auto-approve -var "pipeline_id=${CI_PIPELINE_ID}" -var "artifact_bucket=${ARTIFACT_BUCKET}" -var "artifact_key=${CI_JOB_ID}/app.elf"
- export VERIFIER_IP=$(terraform output -raw verifier_ip)
- echo $VERIFIER_IP > verifier_ip
artifacts:
paths:
- verifier_ip
analyze:
stage: analyze
image: williamyeh/ansible:debian-10
dependencies:
- provision
script:
- VERIFIER_IP=$(cat verifier_ip)
- echo "[verifier]\n$VERIFIER_IP ansible_user=ubuntu" > inventory
- ansible-playbook -i inventory ansible/playbooks/run_wcet.yml --extra-vars "artifact_bucket=${ARTIFACT_BUCKET} artifact_key=${CI_JOB_ID}/app.elf aws_region=${AWS_REGION} result_bucket=${RESULT_BUCKET}"
- aws s3 cp s3://${RESULT_BUCKET}/results/${CI_PIPELINE_ID}-results.json ./results.json
- python3 tools/parse_wcet.py || exit 2
when: on_success
cleanup:
stage: cleanup
image: hashicorp/terraform:1.5
script:
- terraform workspace select ${CI_PIPELINE_ID}
- terraform destroy -auto-approve -var "pipeline_id=${CI_PIPELINE_ID}"
- terraform workspace select default
- terraform workspace delete ${CI_PIPELINE_ID}
when: always
Merge gating
Protect your main branch by requiring the GitLab pipeline job analyze to succeed before merges. That enforces that WCET checks pass as part of the merge, turning timing analysis into a true gated check.
GitHub Actions example
For GitHub Actions, the same pattern applies. Create a workflow that runs terraform apply in an ephemeral environment, then uses a runner to trigger the Ansible run (or uses SSM run command). Use required status checks on pull requests to enforce gating.
# .github/workflows/wcet.yml
name: wcet-verify
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
provision:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
- name: Terraform Apply
run: |
terraform init
terraform workspace new ${GITHUB_RUN_ID} || terraform workspace select ${GITHUB_RUN_ID}
terraform apply -auto-approve -var "pipeline_id=${GITHUB_RUN_ID}"
- name: Save verifier IP
run: terraform output -raw verifier_ip > verifier_ip
- name: Upload IP
uses: actions/upload-artifact@v4
with:
name: verifier-ip
path: verifier_ip
analyze:
needs: provision
runs-on: ubuntu-latest
steps:
- name: Download verifier IP
uses: actions/download-artifact@v4
with:
name: verifier-ip
- name: Run Ansible analysis
uses: dawidd6/action-ansible-playbook@v2
with:
playbook: ansible/playbooks/run_wcet.yml
inventory: "$(cat verifier_ip)"
cleanup:
needs: [provision, analyze]
runs-on: ubuntu-latest
if: always()
steps:
- run: |
terraform workspace select ${GITHUB_RUN_ID}
terraform destroy -auto-approve -var "pipeline_id=${GITHUB_RUN_ID}"
Containerized alternative: Kubernetes Job (EKS / GKE)
If your team prefers Kubernetes, build a container image that bundles the VectorCAST/RocqStat CLI and your policy script, and run it as a Job per PR. This is cleaner for scaling but requires a license server reachable from the cluster.
# k8s/wcet-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: wcet-verify-{{ pipeline_id }}
spec:
template:
spec:
containers:
- name: wcet
image: registry.company/wcet-runner:2026.01
env:
- name: ARTIFACT_S3
value: "s3://..."
- name: LICENSE_SECRET
valueFrom:
secretKeyRef:
name: vector-license
key: license.lic
volumeMounts:
- name: tmp
mountPath: /tmp
restartPolicy: Never
backoffLimit: 0
Operational considerations
License management
Treat your VectorCAST/RocqStat license like any other secret. Use a centrally managed license server where possible and provide short‑lived credentials to ephemeral runners. If file‑based licensing is unavoidable, store license contents only in Vault/SSM and mount at runtime; never bake them in images.
Cost control
- Auto‑destroy infra at pipeline end.
- Reuse warm images or AMIs with preinstalled toolchains to reduce boot time and costs.
- Consider running non‑blocking analyses on spot instances or during off‑peak hours.
Performance and scaling
WCET analysis can be CPU and memory intensive. Benchmark typical runs (2025–2026 reports show significant runtime variance based on binary size). Start with a conservative instance size and scale with a job queue or an autoscaling pool tailored for analysis jobs.
Observability and auditability
- Store analysis artifacts (JSON/XML) in an immutable bucket with lifecycle rules.
- Index results into your traceability system (ELK, Splunk) so you can track WCET regressions over time.
- Emit provenance metadata (commit, pipeline_id, AMI id, tool versions) to comply with audits.
Example failure handling and developer workflow
When a merge request triggers the gated WCET job and the job fails, do the following:
- CI posts the failure status to the merge request and attaches the results.json artifact link.
- The developer reviews the WCET tool output, focusing on the top offenders and any changed functions.
- Open a focused fix: reduce complexity, adjust algorithms, or introduce compiler-level constraints (e.g., link time optimizations) and push a new commit to the MR.
- The pipeline re‑runs automatically; a passing WCET check unblocks the merge.
Security checklist
- Least‑privilege IAM/Service accounts for artifact access.
- Audit all accesses to license endpoints and secrets retrieval.
- Use ephemeral SSH keys or SSM Session Manager instead of persistent keys on VMs.
- Sign and verify tool binaries and AMIs to prevent supply‑chain tampering.
Real‑world example: integrating VectorCAST + RocqStat
With Vector's acquisition of RocqStat in Jan 2026, expect tighter CLI integrations in 2026. If you run VectorCAST today, add RocqStat analysis as a VectorCAST extension or as a downstream CLI invocation. The general approach is the same: call the timing plugin after your unit and integration tests and before the merge gate.
Advanced strategies and future predictions (2026+)
- Unified toolchain pipelines: Vendors will ship combined bundles (VectorCAST + RocqStat) with standardized CI adapters; adopt those adapters as they become available to reduce homegrown integrations.
- Incremental WCET checks: Rather than full WCET runs per MR, run targeted analyses for changed functions and full runs nightly.
- Policy engines: expect to plug WCET rules into policy-as-code engines (Open Policy Agent) so timing checks can participate in broader compliance gates.
- Cloud timing sandboxes: cloud vendors and tool vendors will offer managed timing analysis sandboxes in 2026—evaluate them for scale and auditability, but keep an on‑prem fallback for strict licensing needs.
Actionable takeaways
- Start small: implement a per‑PR ephemeral VM with Terraform and Ansible to run RocqStat/VectorCAST CLI.
- Put thresholds in a versioned wcet.yaml and fail pipelines when exceeded.
- Automate license injection from Vault/SSM and never store it in repo or AMI.
- Use required CI status checks to enforce gating and prevent merges with timing regressions.
Wrap up and next steps
Turning WCET into WCET as Code is an operational shift that yields fewer late surprises, stronger compliance artifacts, and faster developer feedback loops. With Vector consolidating timing tech into established testing suites in 2026, the time to embed timing analysis into gated merges is now. The templates in this article give you a pragmatic starting point—adapt them to your cloud provider and licensing model.
Call to action
Try the sample Terraform + Ansible flow in a sandbox branch today: create a per‑PR workspace, test a simple binary, and enforce a basic wcet.yaml policy. If you want a tailored starter repo based on your CI provider and licensing setup, contact our team at devtools.cloud for a blueprint and implementation help.
Related Reading
- How to Build a Low-Code Connector Between Your CRM and On-Prem Desktop AI
- Building a Subscriber-Funded Music Channel: Lessons from Goalhanger’s 250k Model
- Metadata & Rights: Using Traditional Folk Material in Modern Music Videos (Lessons from BTS’s Title Choice)
- How to Retrofit Smart Curtain Motors: A Step-by-Step Installation Guide
- Lighting for Slow‑Motion Trick Replays: How to Use RGB Lamps and Cheap Rigs to Nail Detail
Related Topics
Unknown
Contributor
Senior editor and content strategist. Writing about technology, design, and the future of digital media. Follow along for deep dives into the industry's moving parts.
Up Next
More stories handpicked for you
Building End‑to‑End Dev Toolchains That Use RISC‑V + Nvidia GPUs
Harnessing AI for Real-Time Translation in DevOps Teams
Beta Testing Made Easy with Android 16 QPR3: A Guide for Developers
Why NVLink Fusion + RISC‑V Matters: Building Hybrid CPU‑GPU Pipelines for AI
Decoding Apple’s Mysterious Pin: What It Means for Developers
From Our Network
Trending stories across our publication group