mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-19 08:01:25 +00:00
1174d7d77f
* refactor: replace SELECT * with explicit column lists Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore: update sqlx offline query cache * chore: update sqlx offline query cache * chore: update sqlx offline query cache with EE support * chore: update sqlx offline query cache, no deletions * chore: update sqlx offline query cache after rebase * fix: correct column names in explicit script query lists - concurrency_limit → concurrent_limit (matches DB column name) - runnable_settings → runnable_settings_handle (matches DB column name) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: add missing delete_after_secs column to script queries Also add integration test covering all explicit-column export queries. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: add workspace export integration test covering all explicit-column queries Covers tarball_workspace (folder, script, resource, resource_type, variable, schedule, usr, group_) and the mcp_oauth_client SELECT query from windmill-mcp. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: add tarball export integration test covering all explicit-column queries Single test creates one of each entity type and exercises every runtime-checked explicit-column query in tarball_workspace. Uses archive_type=tar to avoid zip feature-gate in CI. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs: fix stale verification step and CI contradiction in update-sqlx skill - Regenerate current_files.txt after EE cache restoration so step 4 reports accurate diff - Scope "Never use SQLX_OFFLINE=true" to local prepare (CI legitimately uses it) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs: remove Co-Authored-By from commit skill template * refactor: extract SCRIPT_COLUMNS const to single source of truth Replaces 5 duplicated 44-column lists with a shared const in windmill-types. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
199 lines
6.5 KiB
Rust
199 lines
6.5 KiB
Rust
use sqlx::postgres::Postgres;
|
|
use sqlx::Pool;
|
|
use windmill_test_utils::{initialize_tracing, ApiServer};
|
|
|
|
/// Integration test: exercises every explicit-column query in `tarball_workspace`.
|
|
///
|
|
/// Creates one entity of each type (folder, script, resource, resource_type,
|
|
/// variable, schedule, group) in the test workspace, then calls the tarball
|
|
/// export endpoint with all include_* flags enabled. Success means every
|
|
/// `SELECT col1, col2, ...` list matches the database schema.
|
|
///
|
|
/// Tables exercised (one explicit-column query each):
|
|
/// folder, script, resource, resource_type, variable, schedule, usr, group_
|
|
#[sqlx::test(fixtures("base"))]
|
|
async fn test_tarball_export_all_tables(db: Pool<Postgres>) -> anyhow::Result<()> {
|
|
initialize_tracing().await;
|
|
let server = ApiServer::start(db.clone()).await?;
|
|
let port = server.addr.port();
|
|
let base_url = format!("http://localhost:{port}");
|
|
|
|
let client = windmill_api_client::create_client(&base_url, "SECRET_TOKEN".to_string());
|
|
let http = client.client();
|
|
|
|
// ---- folder ----
|
|
sqlx::query(
|
|
r#"INSERT INTO folder
|
|
(workspace_id, name, display_name, owners, extra_perms, summary)
|
|
VALUES ($1, $2, $3, $4, '{}'::jsonb, $5)"#,
|
|
)
|
|
.bind("test-workspace")
|
|
.bind("test_folder")
|
|
.bind("Test Folder")
|
|
.bind(vec!["u/test-user"])
|
|
.bind("a test folder")
|
|
.execute(&db)
|
|
.await?;
|
|
|
|
// ---- script (exercises the 30-column Script<ScriptRunnableSettingsHandle> query) ----
|
|
client
|
|
.create_script(
|
|
"test-workspace",
|
|
&windmill_api_client::types::NewScript {
|
|
content: "export function main() { return 42; }".to_string(),
|
|
language: windmill_api_client::types::ScriptLang::Bun,
|
|
path: "f/test_folder/test_script".to_string(),
|
|
summary: "test script".to_string(),
|
|
description: "script for export test".to_string(),
|
|
kind: Some("script".to_string()),
|
|
tag: Some("test".to_string()),
|
|
lock: None,
|
|
parent_hash: None,
|
|
schema: Default::default(),
|
|
is_template: None,
|
|
draft_only: None,
|
|
dedicated_worker: None,
|
|
ws_error_handler_muted: None,
|
|
priority: None,
|
|
cache_ttl: None,
|
|
concurrent_limit: None,
|
|
concurrency_time_window_s: None,
|
|
timeout: None,
|
|
delete_after_secs: None,
|
|
restart_unless_cancelled: None,
|
|
visible_to_runner_only: None,
|
|
auto_kind: None,
|
|
on_behalf_of_email: None,
|
|
has_preprocessor: None,
|
|
codebase: None,
|
|
envs: vec![],
|
|
deployment_message: None,
|
|
assets: vec![],
|
|
modules: None,
|
|
concurrency_key: None,
|
|
},
|
|
)
|
|
.await?;
|
|
|
|
// ---- resource ----
|
|
sqlx::query(
|
|
r#"INSERT INTO resource
|
|
(workspace_id, path, value, description, resource_type, created_by)
|
|
VALUES ($1, $2, $3, $4, $5, $6)"#,
|
|
)
|
|
.bind("test-workspace")
|
|
.bind("f/test_folder/test_res")
|
|
.bind(serde_json::json!({"url": "http://example.com"}))
|
|
.bind("test resource")
|
|
.bind("http")
|
|
.bind("test-user")
|
|
.execute(&db)
|
|
.await?;
|
|
|
|
// ---- resource_type ----
|
|
sqlx::query(
|
|
r#"INSERT INTO resource_type
|
|
(workspace_id, name, schema, description, created_by)
|
|
VALUES ($1, $2, $3, $4, $5)"#,
|
|
)
|
|
.bind("test-workspace")
|
|
.bind("http")
|
|
.bind(serde_json::json!({"type": "object"}))
|
|
.bind("HTTP resource type")
|
|
.bind("system")
|
|
.execute(&db)
|
|
.await?;
|
|
|
|
// ---- variable ----
|
|
sqlx::query(
|
|
r#"INSERT INTO variable
|
|
(workspace_id, path, value, is_secret, description, account)
|
|
VALUES ($1, $2, $3, $4, $5, $6)"#,
|
|
)
|
|
.bind("test-workspace")
|
|
.bind("f/test_folder/test_var")
|
|
.bind("test_value")
|
|
.bind(false)
|
|
.bind("test variable")
|
|
.bind(None::<i32>)
|
|
.execute(&db)
|
|
.await?;
|
|
|
|
// ---- schedule ----
|
|
client
|
|
.create_schedule(
|
|
"test-workspace",
|
|
&windmill_api_client::types::NewSchedule {
|
|
schedule: "0 0 0 * * *".to_string(),
|
|
script_path: "f/test_folder/test_script".to_string(),
|
|
path: "f/test_folder/test_schedule".to_string(),
|
|
is_flow: false,
|
|
timezone: "UTC".to_string(),
|
|
args: Default::default(),
|
|
enabled: Some(false),
|
|
description: Some("test schedule".to_string()),
|
|
summary: Some("test schedule".to_string()),
|
|
tag: None,
|
|
cron_version: Some("v2".to_string()),
|
|
on_failure: None,
|
|
on_failure_times: None,
|
|
on_failure_exact: None,
|
|
on_failure_extra_args: None,
|
|
on_recovery: None,
|
|
on_recovery_times: None,
|
|
on_recovery_extra_args: None,
|
|
on_success: None,
|
|
on_success_extra_args: None,
|
|
ws_error_handler_muted: None,
|
|
retry: None,
|
|
no_flow_overlap: None,
|
|
},
|
|
)
|
|
.await?;
|
|
|
|
// ---- group_ (base fixture already has "all", create one more for include_groups) ----
|
|
sqlx::query(
|
|
"INSERT INTO group_ (workspace_id, name, summary, extra_perms) VALUES ($1, $2, $3, '{}'::jsonb)",
|
|
)
|
|
.bind("test-workspace")
|
|
.bind("testgroup")
|
|
.bind("test group")
|
|
.execute(&db)
|
|
.await?;
|
|
|
|
// ---- tarball export: hits ALL explicit-column queries at once ----
|
|
let params = [
|
|
"archive_type=tar",
|
|
"include_schedules=true",
|
|
"include_users=true",
|
|
"include_groups=true",
|
|
"include_settings=true",
|
|
"include_workspace_dependencies=true",
|
|
"settings_version=v1",
|
|
];
|
|
|
|
let resp = http
|
|
.get(format!(
|
|
"{}/api/w/test-workspace/workspaces/tarball?{}",
|
|
base_url,
|
|
params.join("&")
|
|
))
|
|
.bearer_auth("SECRET_TOKEN")
|
|
.send()
|
|
.await?;
|
|
|
|
assert_eq!(
|
|
resp.status(),
|
|
200,
|
|
"tarball export failed: {}",
|
|
resp.text().await.unwrap_or_default()
|
|
);
|
|
|
|
// Verify we got actual bytes back
|
|
let body = resp.bytes().await?;
|
|
assert!(!body.is_empty(), "tarball export returned empty body");
|
|
|
|
Ok(())
|
|
}
|
|
|