fix Tera template compat, remove Python from CI entirely

This commit is contained in:
Adil Hafeez 2026-03-22 23:53:57 +00:00
parent b7fd7771cd
commit cc896bf20f
3 changed files with 54 additions and 29 deletions

View file

@ -52,37 +52,33 @@ jobs:
# Native mode smoke test — build from source & start natively
# ──────────────────────────────────────────────
native-smoke-test:
needs: plano-cli-tests
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-wasip1
- name: Install planoai CLI
working-directory: ./cli
run: |
uv sync
uv tool install .
- name: Download planoai binary
uses: actions/download-artifact@v6
with:
name: planoai-binary
path: crates/target/release/
- name: Make binary executable
run: chmod +x crates/target/release/planoai
- name: Build native binaries
run: planoai build
run: crates/target/release/planoai build
- name: Start plano natively
env:
OPENAI_API_KEY: test-key-not-used
run: planoai up tests/e2e/config_native_smoke.yaml
run: crates/target/release/planoai up tests/e2e/config_native_smoke.yaml
- name: Health check
run: |
@ -100,7 +96,7 @@ jobs:
- name: Stop plano
if: always()
run: planoai down || true
run: crates/target/release/planoai down || true
# ──────────────────────────────────────────────
# Single Docker build — shared by all downstream jobs
@ -147,21 +143,25 @@ jobs:
# Validate plano config
# ──────────────────────────────────────────────
validate-config:
needs: plano-cli-tests
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
- name: Download planoai binary
uses: actions/download-artifact@v6
with:
python-version: "3.14"
name: planoai-binary
path: crates/target/release/
- name: Install planoai
run: pip install -e ./cli
- name: Make binary executable
run: chmod +x crates/target/release/planoai
- name: Validate plano config
run: bash config/validate_plano_config.sh
run: |
export PATH="$PWD/crates/target/release:$PATH"
bash config/validate_plano_config.sh
# ──────────────────────────────────────────────
# Docker security scan (Trivy)

View file

@ -8,13 +8,7 @@ for file in $(find . -name config.yaml -o -name plano_config_full_reference.yaml
rendered_file="$(pwd)/${file}_rendered"
touch "$rendered_file"
PLANO_CONFIG_FILE="$(pwd)/${file}" \
PLANO_CONFIG_SCHEMA_FILE="${SCRIPT_DIR}/plano_config_schema.yaml" \
TEMPLATE_ROOT="${SCRIPT_DIR}" \
ENVOY_CONFIG_TEMPLATE_FILE="envoy.template.yaml" \
PLANO_CONFIG_FILE_RENDERED="$rendered_file" \
ENVOY_CONFIG_FILE_RENDERED="/dev/null" \
python -m planoai.config_generator 2>&1 > /dev/null
planoai validate "$(pwd)/${file}" 2>&1 > /dev/null
if [ $? -ne 0 ]; then
echo "Validation failed for $file"

View file

@ -266,6 +266,10 @@ pub fn validate_and_render(
// Override inferred clusters with endpoints
for (name, details) in &endpoints {
let mut cluster = details.clone();
// Ensure protocol is always set
if cluster.get("protocol").is_none() {
cluster["protocol"] = json!("https");
}
if cluster.get("port").is_none() {
let ep = cluster
.get("endpoint")
@ -279,6 +283,10 @@ pub fn validate_and_render(
cluster["endpoint"] = json!(endpoint);
cluster["port"] = json!(port);
}
// Ensure connect_timeout is set
if cluster.get("connect_timeout").is_none() {
cluster["connect_timeout"] = json!("5s");
}
inferred_clusters.insert(name.clone(), cluster);
}
@ -702,6 +710,29 @@ pub fn validate_and_render(
let mut tera = tera::Tera::default();
let template_content = std::fs::read_to_string(template_path)?;
// Convert Jinja2 syntax to Tera syntax
// indent(N) → indent(width=N)
let template_content = regex::Regex::new(r"indent\((\d+)\)")
.unwrap()
.replace_all(&template_content, "indent(width=$1)")
.to_string();
// var.split(":") | first → var | split(pat=":") | first
let template_content = regex::Regex::new(r#"(\w+)\.split\("([^"]+)"\)"#)
.unwrap()
.replace_all(&template_content, r#"$1 | split(pat="$2")"#)
.to_string();
// default('value') → default(value='value')
let template_content = regex::Regex::new(r"default\('([^']+)'\)")
.unwrap()
.replace_all(&template_content, "default(value='$1')")
.to_string();
// replace(" ", "_") → replace(from=" ", to="_")
let template_content = regex::Regex::new(r#"replace\("([^"]*)",\s*"([^"]*)"\)"#)
.unwrap()
.replace_all(&template_content, r#"replace(from="$1", to="$2")"#)
.to_string();
// dict.items() → dict (Tera iterates dicts directly)
let template_content = template_content.replace(".items()", "");
tera.add_raw_template(template_filename, &template_content)?;
let mut context = tera::Context::new();