-
Notifications
You must be signed in to change notification settings - Fork 649
CI - Parallelize smoketests #3702
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
bfops
wants to merge
52
commits into
add/cargo-ci
Choose a base branch
from
bfops/parallel-smoketests
base: add/cargo-ci
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 40 commits
Commits
Show all changes
52 commits
Select commit
Hold shift + click to select a range
7789f2f
[bfops/fix-list-tests]: Fix running smoketests --list
bfops 3d1d6b0
Merge branch 'master' into bfops/fix-list-tests
bfops 8bd2b44
[bfops/share-python-deps]: Add smoketests/requirements.txt
bfops 13ed948
[bfops/fix-list-tests]: Merge remote-tracking branch 'origin/bfops/sh…
bfops b8197eb
Merge branch 'master' into bfops/share-python-deps
bfops a4c3ca8
[bfops/share-python-deps]: fix
bfops fbc5e24
[bfops/fix-list-tests]: Merge remote-tracking branch 'origin/bfops/sh…
bfops db51dc7
[bfops/fix-list-tests]: restore
bfops fae85d5
[bfops/fix-list-tests]: print any failed
bfops e7f9f9f
[bfops/share-python-deps]: review
bfops 9aca3b7
[bfops/share-python-deps]: review
bfops a8fee32
[bfops/fix-list-tests]: Merge remote-tracking branch 'origin/bfops/sh…
bfops 5f1c35d
[bfops/parallel-smoketests]: empty
bfops 972ee33
[bfops/parallel-smoketests]: Merge remote-tracking branch 'origin/mas…
bfops cd878b6
Merge branch 'master' into bfops/parallel-smoketests
bfops 0dbf4a5
[bfops/parallel-smoketests]: Merge remote-tracking branch 'origin/add…
bfops 2dc780c
[bfops/parallel-smoketests]: remove python parallel flags
bfops 910f3f0
[bfops/parallel-smoketests]: Merge branch 'bfops/parallel-smoketests'…
bfops 7fe19dd
[bfops/parallel-smoketests]: wip
bfops deb123a
[bfops/parallel-smoketests]: review
bfops 282ece6
[bfops/parallel-smoketests]: Start server as part of running smoketests
bfops f095a1d
[bfops/parallel-smoketests]: WIP
bfops 336337a
[bfops/parallel-smoketests]: review
bfops 38859ab
[bfops/parallel-smoketests]: review
bfops 5940d57
[bfops/parallel-smoketests]: Merge remote-tracking branch 'origin/add…
bfops 8ae1971
[bfops/parallel-smoketests]: fix workflow file
bfops 9bbe781
[bfops/parallel-smoketests]: maybe fix?
bfops 3937768
[bfops/parallel-smoketests]: fix copy
bfops f7e7893
[bfops/parallel-smoketests]: fix
bfops 680042e
[bfops/parallel-smoketests]: review
bfops 60de57d
[bfops/ci-start-server]: revert
bfops e7443f4
[bfops/ci-start-server]: review
bfops 5327956
[bfops/ci-start-server]: revert
bfops 6fd17a0
[bfops/parallel-smoketests]: Merge remote-tracking branch 'origin/bfo…
bfops 9afb403
[bfops/parallel-smoketests]: Revert "[bfops/ci-start-server]: revert"
bfops 961d8ba
[bfops/parallel-smoketests]: WIP
bfops 3516f69
[bfops/parallel-smoketests]: WIP
bfops a0ccb9e
[bfops/parallel-smoketests]: WIP
bfops cd2db36
[bfops/parallel-smoketests]: builds with random port selection / proj…
bfops 0457534
[bfops/parallel-smoketests]: add --local-only
bfops 9eef7cb
[bfops/parallel-smoketests]: add smoketests --list=json
bfops a514921
[bfops/parallel-smoketests]: WIP parallel logic
bfops 45ee326
[bfops/parallel-smoketests]: custom python path option
bfops 46793a4
[bfops/parallel-smoketests]: actual parallel
bfops f3944f3
[bfops/parallel-smoketests]: TODO
bfops e98d525
[bfops/parallel-smoketests]: review
bfops 52e3f6e
[bfops/parallel-smoketests]: use parallel smoketests in CI
bfops 40cb0de
[bfops/parallel-smoketests]: Don't build CLI in smoketests if we're a…
bfops 83f3fff
[bfops/parallel-smoketests]: consolidate builds, and fix
bfops 75b47ac
[bfops/parallel-smoketests]: todos
bfops 73548c1
[bfops/parallel-smoketests]: Pre-build in non-parallel case too
bfops 04eeb8c
[bfops/parallel-smoketests]: sanitize cargo env
bfops File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,10 @@ | ||
| use anyhow::{bail, Result}; | ||
| use anyhow::{bail, Context, Result}; | ||
| use clap::{CommandFactory, Parser, Subcommand}; | ||
| use duct::cmd; | ||
| use log::warn; | ||
| use std::collections::HashMap; | ||
| use std::path::Path; | ||
| use std::net::TcpListener; | ||
| use std::path::{Path, PathBuf}; | ||
| use std::{env, fs}; | ||
|
|
||
| const README_PATH: &str = "tools/ci/README.md"; | ||
|
|
@@ -51,6 +53,20 @@ enum CiCmd { | |
| /// | ||
| /// Executes the smoketests suite with some default exclusions. | ||
| Smoketests { | ||
| #[arg( | ||
| long = "start-server", | ||
| default_value_t = true, | ||
| long_help = "Whether to start a local SpacetimeDB server before running smoketests" | ||
| )] | ||
| start_server: bool, | ||
| #[arg( | ||
| long = "docker", | ||
| value_name = "COMPOSE_FILE", | ||
| num_args(0..=1), | ||
| default_missing_value = "docker-compose.yml", | ||
| long_help = "Use docker for smoketests, specifying a docker compose file. If no value is provided, docker-compose.yml is used by default. This cannot be combined with --start-server." | ||
| )] | ||
| docker: Option<String>, | ||
| #[arg( | ||
| trailing_var_arg = true, | ||
| long_help = "Additional arguments to pass to the smoketests runner. These are usually set by the CI environment, such as `-- --docker`" | ||
|
|
@@ -133,6 +149,134 @@ fn run_bash(cmdline: &str, additional_env: &[(&str, &str)]) -> Result<()> { | |
| Ok(()) | ||
| } | ||
|
|
||
| #[derive(Debug, Clone)] | ||
| pub enum StartServer { | ||
| No, | ||
| Yes { random_port: bool }, | ||
| Docker { compose_file: PathBuf, random_port: bool }, | ||
| } | ||
|
|
||
| #[derive(Debug, Clone)] | ||
| pub enum ServerState { | ||
| None, | ||
| Yes { pid: i32 }, | ||
| Docker { compose_file: PathBuf, project: String }, | ||
| } | ||
|
|
||
| fn find_free_port() -> Result<u16> { | ||
| let listener = TcpListener::bind("127.0.0.1:0").context("failed to bind to an ephemeral port")?; | ||
| let port = listener | ||
| .local_addr() | ||
| .context("failed to read local address for ephemeral port")? | ||
| .port(); | ||
| drop(listener); | ||
| Ok(port) | ||
| } | ||
|
|
||
| fn run_smoketests_batch(server_mode: StartServer, args: &[String]) -> Result<()> { | ||
| let server_state = match server_mode { | ||
| StartServer::No => ServerState::None, | ||
| StartServer::Docker { | ||
| compose_file, | ||
| random_port, | ||
| } => { | ||
| println!("Starting server.."); | ||
| let env_string; | ||
| let project; | ||
| if random_port { | ||
| let server_port = find_free_port()?; | ||
| let pg_port = find_free_port()?; | ||
| let tracy_port = find_free_port()?; | ||
| env_string = format!("STDB_PORT={server_port} STDB_PG_PORT={pg_port} STDB_TRACY_PORT={tracy_port}"); | ||
| project = format!("spacetimedb-smoketests-{server_port}"); | ||
| } else { | ||
| env_string = String::new(); | ||
| project = "spacetimedb-smoketests".to_string(); | ||
| }; | ||
| let compose_str = compose_file.to_string_lossy(); | ||
| bash!(&format!( | ||
| "{env_string} docker compose -f {compose_str} --project {project} up -d" | ||
| ))?; | ||
| ServerState::Docker { compose_file, project } | ||
| } | ||
| StartServer::Yes { random_port } => { | ||
| // Pre-build so that `cargo run -p spacetimedb-cli` will immediately start. Otherwise we risk starting the tests | ||
| // before the server is up. | ||
| bash!("cargo build -p spacetimedb-cli -p spacetimedb-standalone")?; | ||
|
|
||
| // TODO: Make sure that this isn't brittle / multiple parallel batches don't grab the same port | ||
| let arg_string = if random_port { | ||
| let server_port = find_free_port()?; | ||
| let pg_port = find_free_port()?; | ||
| &format!("--listen-addr 0.0.0.0:{server_port} --pg-port {pg_port}") | ||
| } else { | ||
| "--pg-port 5432" | ||
| }; | ||
| println!("Starting server.."); | ||
| let pid_str; | ||
| if cfg!(target_os = "windows") { | ||
| pid_str = cmd!( | ||
| "powershell", | ||
| "-NoProfile", | ||
| "-Command", | ||
| &format!( | ||
| "$p = Start-Process cargo -ArgumentList 'run -p spacetimedb-cli -- start {arg_string}' -PassThru; $p.Id" | ||
| ) | ||
| ) | ||
| .read() | ||
| .unwrap_or_default(); | ||
| } else { | ||
| pid_str = cmd!( | ||
| "bash", | ||
| "-lc", | ||
| &format!("nohup cargo run -p spacetimedb-cli -- start {arg_string} >/dev/null 2>&1 & echo $!") | ||
| ) | ||
| .read() | ||
| .unwrap_or_default(); | ||
| } | ||
| ServerState::Yes { | ||
| pid: pid_str | ||
| .trim() | ||
| .parse::<i32>() | ||
| .expect("Failed to get PID of started process"), | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| // TODO: does this work on windows? | ||
|
||
| let py3_available = cmd!("bash", "-lc", "command -v python3 >/dev/null 2>&1") | ||
| .run() | ||
| .map(|s| s.status.success()) | ||
| .unwrap_or(false); | ||
| let python = if py3_available { "python3" } else { "python" }; | ||
|
|
||
| println!("Running smoketests.."); | ||
| let test_result = bash!(&format!("{python} -m smoketests {}", args.join(" "))); | ||
|
|
||
| // TODO: Make an effort to run the wind-down behavior if we ctrl-C this process | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. resolve this TODO |
||
| match server_state { | ||
| ServerState::None => {} | ||
| ServerState::Docker { compose_file, project } => { | ||
| println!("Shutting down server.."); | ||
| let compose_str = compose_file.to_string_lossy(); | ||
| let _ = bash!(&format!("docker compose -f {compose_str} --project {project} down")); | ||
| } | ||
| ServerState::Yes { pid } => { | ||
| println!("Shutting down server.."); | ||
| if cfg!(target_os = "windows") { | ||
| let _ = bash!(&format!( | ||
| "powershell -NoProfile -Command \"Stop-Process -Id {} -Force -ErrorAction SilentlyContinue\"", | ||
| pid | ||
| )); | ||
| } else { | ||
| let _ = bash!(&format!("kill {}", pid)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| test_result | ||
| } | ||
|
|
||
| fn main() -> Result<()> { | ||
| let cli = Cli::parse(); | ||
|
|
||
|
|
@@ -168,14 +312,32 @@ fn main() -> Result<()> { | |
| bash!("cargo run -p spacetimedb-cli -- build --project-path modules/module-test")?; | ||
| } | ||
|
|
||
| Some(CiCmd::Smoketests { args }) => { | ||
| // On some systems, there is no `python`, but there is `python3`. | ||
| let py3_available = cmd!("bash", "-lc", "command -v python3 >/dev/null 2>&1") | ||
| .run() | ||
| .map(|s| s.status.success()) | ||
| .unwrap_or(false); | ||
| let python = if py3_available { "python3" } else { "python" }; | ||
| bash!(&format!("{python} -m smoketests {}", args.join(" ")))?; | ||
| Some(CiCmd::Smoketests { | ||
| start_server, | ||
| docker, | ||
| args, | ||
| }) => { | ||
| let start_server = match (start_server, docker.as_ref()) { | ||
| (start_server, Some(compose_file)) => { | ||
| if !start_server { | ||
| warn!("--docker implies --start-server=true"); | ||
| } | ||
| StartServer::Docker { | ||
| random_port: false, | ||
| compose_file: compose_file.into(), | ||
| } | ||
| } | ||
| (true, None) => StartServer::Yes { random_port: false }, | ||
| (false, None) => StartServer::No, | ||
| }; | ||
| let mut args = args.to_vec(); | ||
| if let Some(compose_file) = docker.as_ref() { | ||
| // Note that we do not assume that the user wants to pass --docker to the tests. We leave them the power to | ||
| // run the server in docker while still retaining full control over what tests they want. | ||
| args.push("--compose-file".to_string()); | ||
| args.push(compose_file.to_string()); | ||
| } | ||
| run_smoketests_batch(start_server, &args)?; | ||
| } | ||
|
|
||
| Some(CiCmd::UpdateFlow { | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resolve this TODO