* feat: add CI test scripts with auto-trigger on deploy Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: fix annotation parser early return and handle renames correctly Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: move CI test results to top of script/flow detail pages Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: improve CI test results spacing, icon, and remove pass label Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: support one-line annotation and use script/path format Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: move CI test trigger logic to EE Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: move CI badge next to New badge and add deduplicated CI summary Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: add CI test e2e tests and fix nullable column annotations Add integration tests for CI test annotation parsing (creates/removes ci_test_reference rows) and the CI test results API (single + batch endpoints). Add backend test for auto-trigger on deploy (private+python). Fix sqlx LEFT JOIN LATERAL nullable column annotations in get_ci_test_results and get_ci_test_results_batch queries — sqlx cannot infer nullability from LATERAL subqueries, causing runtime decode errors when no matching job exists. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix build/sqlx * fix * feat: CI test improvements and templates - Fix windmill-dep-map/private feature propagation in worker, api-scripts, and api-flows Cargo.toml so CI test triggers actually fire in EE mode - Clone ci_test_reference rows during workspace fork - Add polling to CiTestResults component (refetch every 3s while running) - Add running state and auto-refresh to ForkWorkspaceBanner CI summary - Add yellow "CI test" badge on script list rows and detail page - Fix Library badge border color (remove indigo border override) - Add CI Test TypeScript and CI Test Python templates in ScriptBuilder - Update sqlx offline cache - Add debug tracing for CI test trigger in worker_lockfiles Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: add missing children prop to WorkspaceDeployLayout Fixes svelte-fast-check type error when passing named snippets as children content inside the component tag. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address PR review feedback - Remove empty wrapper divs around CiTestResults, move mb-4 into component - Add batch endpoint size cap (max 200 items) - Add ON DELETE CASCADE to ci_test_reference workspace FK (new migration) - Downgrade CI test trigger logs from info to debug - Fix false-positive polling: only treat status='running' as running, not null status (CiTestResults, CompareWorkspaces, ForkWorkspaceBanner) - Fix test numbering in integration tests Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to latest EE commit Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to d9d68c2406df0b59f413ea0b2cb24780a9817d04 This commit updates the EE repository reference after PR #516 was merged in windmill-ee-private. Previous ee-repo-ref: d7ccd9b86da99ec056a0e8708e3637d64290387a New ee-repo-ref: d9d68c2406df0b59f413ea0b2cb24780a9817d04 Automated by sync-ee-ref workflow. * fix: treat queued jobs (job_id set, null status) as running Jobs that have been pushed but not yet picked up by a worker have a job_id but null status. Treat these as 'running' to avoid showing misleading 'pass' badges or '0 passing'. Tests that were never triggered (no job_id, null status) remain neutral/hidden. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: hugocasa <hugo@casademont.ch> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
117 lines
4.0 KiB
Rust
117 lines
4.0 KiB
Rust
#[cfg(all(feature = "python", feature = "private"))]
|
|
mod ci_tests {
|
|
use std::collections::HashMap;
|
|
|
|
use sqlx::{Pool, Postgres};
|
|
use tokio_stream::StreamExt;
|
|
|
|
use windmill_api_client::types::{NewScript, ScriptLang};
|
|
use windmill_test_utils::{in_test_worker, init_client, listen_for_completed_jobs};
|
|
|
|
fn quick_ns(content: &str, path: &str, parent_hash: Option<String>) -> NewScript {
|
|
NewScript {
|
|
content: content.into(),
|
|
language: ScriptLang::Python3,
|
|
lock: None,
|
|
parent_hash,
|
|
path: path.into(),
|
|
concurrent_limit: None,
|
|
concurrency_time_window_s: None,
|
|
cache_ttl: None,
|
|
dedicated_worker: None,
|
|
description: "".to_string(),
|
|
draft_only: None,
|
|
envs: vec![],
|
|
is_template: None,
|
|
kind: None,
|
|
summary: "".to_string(),
|
|
tag: None,
|
|
schema: HashMap::new(),
|
|
ws_error_handler_muted: Some(false),
|
|
priority: None,
|
|
delete_after_secs: None,
|
|
timeout: None,
|
|
restart_unless_cancelled: None,
|
|
deployment_message: None,
|
|
concurrency_key: None,
|
|
visible_to_runner_only: None,
|
|
auto_kind: None,
|
|
codebase: None,
|
|
has_preprocessor: None,
|
|
on_behalf_of_email: None,
|
|
assets: vec![],
|
|
modules: None,
|
|
}
|
|
}
|
|
|
|
/// Test 2: Deploying a script automatically triggers CI test jobs for test scripts
|
|
/// that reference it via the `# test:` annotation.
|
|
#[sqlx::test(fixtures("base"))]
|
|
async fn test_ci_test_trigger_on_deploy(db: Pool<Postgres>) -> anyhow::Result<()> {
|
|
let (client, port, _s) = init_client(db.clone()).await;
|
|
|
|
// Step 1: Create the test script with a CI annotation targeting deploy_target.
|
|
// This inserts a ci_test_reference row.
|
|
client
|
|
.create_script(
|
|
"test-workspace",
|
|
&quick_ns(
|
|
"# test: script/u/test-user/deploy_target\ndef main():\n return True",
|
|
"u/test-user/ci_test_for_deploy",
|
|
None,
|
|
),
|
|
)
|
|
.await
|
|
.unwrap();
|
|
|
|
// Process the test script's dependency (lock generation) job
|
|
let mut completed = listen_for_completed_jobs(&db).await;
|
|
in_test_worker(&db, completed.next(), port).await;
|
|
|
|
// Step 2: Create the target script. Its dependency job, once processed,
|
|
// will call trigger_ci_tests_for_item which finds our test script.
|
|
client
|
|
.create_script(
|
|
"test-workspace",
|
|
&quick_ns(
|
|
"def main():\n return 42",
|
|
"u/test-user/deploy_target",
|
|
None,
|
|
),
|
|
)
|
|
.await
|
|
.unwrap();
|
|
|
|
// Process the target script's dependency job → CI trigger fires in tokio::spawn
|
|
let mut completed = listen_for_completed_jobs(&db).await;
|
|
in_test_worker(&db, completed.next(), port).await;
|
|
|
|
// Give the spawned trigger task time to push the CI test job
|
|
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
|
|
|
|
// Verify a CI test job was queued
|
|
let ci_jobs = sqlx::query!(
|
|
"SELECT j.id, j.runnable_path, j.trigger_kind::text as trigger_kind \
|
|
FROM v2_job j \
|
|
WHERE j.workspace_id = 'test-workspace' \
|
|
AND j.trigger_kind = 'ci_test'"
|
|
)
|
|
.fetch_all(&db)
|
|
.await?;
|
|
|
|
assert_eq!(ci_jobs.len(), 1, "expected exactly 1 CI test job");
|
|
assert_eq!(
|
|
ci_jobs[0].runnable_path.as_deref(),
|
|
Some("u/test-user/ci_test_for_deploy"),
|
|
"CI test job should run the test script"
|
|
);
|
|
assert_eq!(
|
|
ci_jobs[0].trigger_kind.as_deref(),
|
|
Some("ci_test"),
|
|
"trigger_kind should be ci_test"
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
}
|