Skip to content

Commit 3536a18

Browse files
authored
Initial template for the Extra Tests workflow (#10636)
- Closes #10618 - adjusts some edge case tests in Snowflake
1 parent db669a6 commit 3536a18

File tree

13 files changed

+314
-117
lines changed

13 files changed

+314
-117
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# This file is auto-generated. Do not edit it manually!
2+
# Edit the enso_build::ci_gen module instead and run `cargo run --package enso-build-ci-gen`.
3+
4+
name: Extra Nightly Tests
5+
on:
6+
schedule:
7+
- cron: 0 3 * * *
8+
workflow_dispatch:
9+
inputs:
10+
clean_build_required:
11+
description: Clean before and after the run.
12+
required: false
13+
type: boolean
14+
default: false
15+
jobs:
16+
enso-build-ci-gen-job-snowflake-tests-linux-x86_64:
17+
name: Snowflake Tests (linux, x86_64)
18+
runs-on:
19+
- self-hosted
20+
- Linux
21+
steps:
22+
- if: startsWith(runner.name, 'GitHub Actions') || startsWith(runner.name, 'Hosted Agent')
23+
name: Installing wasm-pack
24+
uses: jetli/[email protected]
25+
with:
26+
version: v0.10.2
27+
- name: Expose Artifact API and context information.
28+
uses: actions/github-script@v7
29+
with:
30+
script: "\n core.exportVariable(\"ACTIONS_RUNTIME_TOKEN\", process.env[\"ACTIONS_RUNTIME_TOKEN\"])\n core.exportVariable(\"ACTIONS_RUNTIME_URL\", process.env[\"ACTIONS_RUNTIME_URL\"])\n core.exportVariable(\"GITHUB_RETENTION_DAYS\", process.env[\"GITHUB_RETENTION_DAYS\"])\n console.log(context)\n "
31+
- name: Checking out the repository
32+
uses: actions/checkout@v4
33+
with:
34+
clean: false
35+
submodules: recursive
36+
- name: Build Script Setup
37+
run: ./run --help || (git clean -ffdx && ./run --help)
38+
env:
39+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40+
- if: "(contains(github.event.pull_request.labels.*.name, 'CI: Clean build required') || inputs.clean_build_required)"
41+
name: Clean before
42+
run: ./run git-clean
43+
env:
44+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
45+
- run: ./run backend test std-snowflake
46+
env:
47+
ENSO_SNOWFLAKE_ACCOUNT: ${{ secrets.ENSO_SNOWFLAKE_ACCOUNT }}
48+
ENSO_SNOWFLAKE_DATABASE: ${{ secrets.ENSO_SNOWFLAKE_DATABASE }}
49+
ENSO_SNOWFLAKE_PASSWORD: ${{ secrets.ENSO_SNOWFLAKE_PASSWORD }}
50+
ENSO_SNOWFLAKE_SCHEMA: ${{ secrets.ENSO_SNOWFLAKE_SCHEMA }}
51+
ENSO_SNOWFLAKE_USER: ${{ secrets.ENSO_SNOWFLAKE_USER }}
52+
ENSO_SNOWFLAKE_WAREHOUSE: ${{ secrets.ENSO_SNOWFLAKE_WAREHOUSE }}
53+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
54+
- if: (success() || failure()) && github.event.pull_request.head.repo.full_name == github.repository
55+
name: Extra Library Test Reporter
56+
uses: dorny/test-reporter@v1
57+
with:
58+
max-annotations: 50
59+
name: Extra Library Tests Report (GraalVM CE, linux, x86_64)
60+
path: ${{ env.ENSO_TEST_JUNIT_DIR }}/*/*.xml
61+
path-replace-backslashes: true
62+
reporter: java-junit
63+
- if: failure() && runner.os == 'Windows'
64+
name: List files if failed (Windows)
65+
run: Get-ChildItem -Force -Recurse
66+
- if: failure() && runner.os != 'Windows'
67+
name: List files if failed (non-Windows)
68+
run: ls -lAR
69+
- if: "(always()) && (contains(github.event.pull_request.labels.*.name, 'CI: Clean build required') || inputs.clean_build_required)"
70+
name: Clean after
71+
run: ./run git-clean
72+
env:
73+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
74+
env:
75+
GRAAL_EDITION: GraalVM CE
76+
permissions:
77+
checks: write
78+
env:
79+
ENSO_BUILD_SKIP_VERSION_CHECK: "true"

build/build/paths.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
gui-tests.yml:
1111
gui.yml:
1212
engine-nightly.yml:
13+
extra-nightly-tests.yml:
1314
nightly.yml:
1415
promote.yml:
1516
release.yml:

build/build/src/ci_gen.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,14 @@ pub mod secret {
119119
pub const APPLE_NOTARIZATION_PASSWORD: &str = "APPLE_NOTARIZATION_PASSWORD";
120120
pub const APPLE_NOTARIZATION_TEAM_ID: &str = "APPLE_NOTARIZATION_TEAM_ID";
121121

122+
// === Snowflake Test Account ===
123+
pub const ENSO_SNOWFLAKE_ACCOUNT: &str = "ENSO_SNOWFLAKE_ACCOUNT";
124+
pub const ENSO_SNOWFLAKE_USER: &str = "ENSO_SNOWFLAKE_USER";
125+
pub const ENSO_SNOWFLAKE_PASSWORD: &str = "ENSO_SNOWFLAKE_PASSWORD";
126+
pub const ENSO_SNOWFLAKE_DATABASE: &str = "ENSO_SNOWFLAKE_DATABASE";
127+
pub const ENSO_SNOWFLAKE_SCHEMA: &str = "ENSO_SNOWFLAKE_SCHEMA";
128+
pub const ENSO_SNOWFLAKE_WAREHOUSE: &str = "ENSO_SNOWFLAKE_WAREHOUSE";
129+
122130
// === Windows Code Signing ===
123131
/// Name of the GitHub Actions secret that stores path to the Windows code signing certificate
124132
/// within the runner.
@@ -682,6 +690,22 @@ pub fn engine_nightly() -> Result<Workflow> {
682690
Ok(workflow)
683691
}
684692

693+
pub fn extra_nightly_tests() -> Result<Workflow> {
694+
let on = Event {
695+
// We start at running the tests daily at 3 am, but we may adjust to run it every few days
696+
// or only once a week.
697+
schedule: vec![Schedule::new("0 3 * * *")?],
698+
workflow_dispatch: Some(manual_workflow_dispatch()),
699+
..default()
700+
};
701+
let mut workflow = Workflow { name: "Extra Nightly Tests".into(), on, ..default() };
702+
703+
// We run the extra tests only on Linux, as they should not contain any platform-specific
704+
// behavior.
705+
let target = (OS::Linux, Arch::X86_64);
706+
workflow.add(target, job::SnowflakeTests {});
707+
Ok(workflow)
708+
}
685709

686710
pub fn engine_benchmark() -> Result<Workflow> {
687711
benchmark_workflow("Benchmark Engine", "backend benchmark runtime", Some(4 * 60))
@@ -751,6 +775,7 @@ pub fn generate(
751775
(repo_root.nightly_yml.to_path_buf(), nightly()?),
752776
(repo_root.scala_new_yml.to_path_buf(), backend()?),
753777
(repo_root.engine_nightly_yml.to_path_buf(), engine_nightly()?),
778+
(repo_root.extra_nightly_tests_yml.to_path_buf(), extra_nightly_tests()?),
754779
(repo_root.gui_yml.to_path_buf(), gui()?),
755780
(repo_root.gui_tests_yml.to_path_buf(), gui_tests()?),
756781
(repo_root.engine_benchmark_yml.to_path_buf(), engine_benchmark()?),

build/build/src/ci_gen/job.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,57 @@ impl JobArchetype for StandardLibraryTests {
256256
}
257257
}
258258

259+
#[derive(Clone, Copy, Debug)]
260+
pub struct SnowflakeTests {}
261+
262+
const GRAAL_EDITION_FOR_EXTRA_TESTS: graalvm::Edition = graalvm::Edition::Community;
263+
264+
impl JobArchetype for SnowflakeTests {
265+
fn job(&self, target: Target) -> Job {
266+
let job_name = "Snowflake Tests";
267+
let mut job = RunStepsBuilder::new("backend test std-snowflake")
268+
.customize(move |step| {
269+
let main_step = step
270+
.with_secret_exposed_as(
271+
secret::ENSO_SNOWFLAKE_ACCOUNT,
272+
crate::libraries_tests::snowflake::env::ENSO_SNOWFLAKE_ACCOUNT,
273+
)
274+
.with_secret_exposed_as(
275+
secret::ENSO_SNOWFLAKE_USER,
276+
crate::libraries_tests::snowflake::env::ENSO_SNOWFLAKE_USER,
277+
)
278+
.with_secret_exposed_as(
279+
secret::ENSO_SNOWFLAKE_PASSWORD,
280+
crate::libraries_tests::snowflake::env::ENSO_SNOWFLAKE_PASSWORD,
281+
)
282+
.with_secret_exposed_as(
283+
secret::ENSO_SNOWFLAKE_DATABASE,
284+
crate::libraries_tests::snowflake::env::ENSO_SNOWFLAKE_DATABASE,
285+
)
286+
.with_secret_exposed_as(
287+
secret::ENSO_SNOWFLAKE_SCHEMA,
288+
crate::libraries_tests::snowflake::env::ENSO_SNOWFLAKE_SCHEMA,
289+
)
290+
.with_secret_exposed_as(
291+
secret::ENSO_SNOWFLAKE_WAREHOUSE,
292+
crate::libraries_tests::snowflake::env::ENSO_SNOWFLAKE_WAREHOUSE,
293+
);
294+
vec![
295+
main_step,
296+
step::extra_stdlib_test_reporter(target, GRAAL_EDITION_FOR_EXTRA_TESTS),
297+
]
298+
})
299+
.build_job(job_name, target)
300+
.with_permission(Permission::Checks, Access::Write);
301+
job.env(env::GRAAL_EDITION, GRAAL_EDITION_FOR_EXTRA_TESTS);
302+
job
303+
}
304+
305+
fn key(&self, (os, arch): Target) -> String {
306+
format!("{}-{os}-{arch}", self.id_key_base())
307+
}
308+
}
309+
259310
#[derive(Clone, Copy, Debug)]
260311
pub struct Lint;
261312

build/build/src/ci_gen/step.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,10 @@ pub fn engine_test_reporter((os, arch): Target, graal_edition: graalvm::Edition)
4242
let path = format!("{}/*.xml", env_expression(&paths::ENSO_TEST_JUNIT_DIR));
4343
test_reporter(step_name, report_name, path)
4444
}
45+
46+
pub fn extra_stdlib_test_reporter((os, arch): Target, graal_edition: graalvm::Edition) -> Step {
47+
let step_name = "Extra Library Test Reporter";
48+
let report_name = format!("Extra Library Tests Report ({graal_edition}, {os}, {arch})");
49+
let path = format!("{}/*/*.xml", env_expression(&paths::ENSO_TEST_JUNIT_DIR));
50+
test_reporter(step_name, report_name, path)
51+
}

build/build/src/engine.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ pub enum Tests {
9797
Jvm,
9898
#[clap(alias = "stdlib")]
9999
StandardLibrary,
100+
StdSnowflake,
100101
}
101102

102103
impl Benchmarks {
@@ -118,7 +119,7 @@ pub struct BuildConfigurationFlags {
118119
/// Run JVM tests.
119120
pub test_jvm: bool,
120121
/// Whether the Enso standard library should be tested.
121-
pub test_standard_library: bool,
122+
pub test_standard_library: Option<StandardLibraryTestsSelection>,
122123
/// Whether benchmarks are compiled.
123124
///
124125
/// Note that this does not run the benchmarks, only ensures that they are buildable.
@@ -147,6 +148,12 @@ pub struct BuildConfigurationFlags {
147148
pub verify_packages: bool,
148149
}
149150

151+
#[derive(Clone, Debug)]
152+
pub enum StandardLibraryTestsSelection {
153+
All,
154+
Selected(Vec<String>),
155+
}
156+
150157
impl From<BuildConfigurationFlags> for BuildConfigurationResolved {
151158
fn from(value: BuildConfigurationFlags) -> Self {
152159
Self::new(value)
@@ -170,7 +177,7 @@ impl BuildConfigurationResolved {
170177

171178
// Check for components that require Enso Engine runner. Basically everything that needs to
172179
// run pure Enso code.
173-
if config.test_standard_library
180+
if config.test_standard_library.is_some()
174181
|| config.execute_benchmarks.contains(&Benchmarks::Enso)
175182
|| config.check_enso_benchmarks
176183
{
@@ -195,7 +202,7 @@ impl BuildConfigurationFlags {
195202
self.build_engine_package
196203
|| self.build_launcher_bundle
197204
|| self.build_project_manager_bundle
198-
|| self.test_standard_library
205+
|| self.test_standard_library.is_some()
199206
|| self.build_native_runner
200207
}
201208

@@ -206,13 +213,29 @@ impl BuildConfigurationFlags {
206213
pub fn build_launcher_package(&self) -> bool {
207214
self.build_launcher_package || self.build_launcher_bundle
208215
}
216+
217+
pub fn add_standard_library_test_selection(
218+
&mut self,
219+
selection: StandardLibraryTestsSelection,
220+
) {
221+
use StandardLibraryTestsSelection::*;
222+
let combined_selection = match (self.test_standard_library.take(), selection) {
223+
(None, selection) => selection,
224+
(Some(All), _) | (_, All) => All,
225+
(Some(Selected(mut selection)), Selected(new_selection)) => {
226+
selection.extend(new_selection);
227+
Selected(selection)
228+
}
229+
};
230+
self.test_standard_library = Some(combined_selection);
231+
}
209232
}
210233

211234
impl Default for BuildConfigurationFlags {
212235
fn default() -> Self {
213236
Self {
214237
test_jvm: false,
215-
test_standard_library: false,
238+
test_standard_library: None,
216239
build_benchmarks: false,
217240
check_enso_benchmarks: false,
218241
execute_benchmarks: default(),

build/build/src/engine/context.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ impl RunContext {
243243

244244

245245
let _test_results_upload_guard =
246-
if self.config.test_jvm || self.config.test_standard_library {
246+
if self.config.test_jvm || self.config.test_standard_library.is_some() {
247247
// If we run tests, make sure that old and new results won't end up mixed together.
248248
let test_results_dir = ENSO_TEST_JUNIT_DIR
249249
.get()
@@ -393,14 +393,16 @@ impl RunContext {
393393
Ok(())
394394
};
395395

396-
if self.config.test_standard_library {
397-
enso.run_tests(IrCaches::No, &sbt, PARALLEL_ENSO_TESTS).await?;
396+
match &self.config.test_standard_library {
397+
Some(selection) => {
398+
enso.run_tests(IrCaches::No, &sbt, PARALLEL_ENSO_TESTS, selection.clone()).await?;
399+
}
400+
None => {}
398401
}
399402

400403
perhaps_test_java_generated_from_rust_job.await.transpose()?;
401404

402405
// === Run benchmarks ===
403-
debug!("Running benchmarks.");
404406
let build_benchmark_task = if self.config.build_benchmarks {
405407
let build_benchmark_task_names = [
406408
"runtime-benchmarks/compile",
@@ -422,6 +424,7 @@ impl RunContext {
422424
build_benchmark_task.as_deref().into_iter().chain(execute_benchmark_tasks);
423425
let benchmark_command = Sbt::sequential_tasks(build_and_execute_benchmark_task);
424426
if !benchmark_command.is_empty() {
427+
debug!("Running benchmarks.");
425428
sbt.call_arg(benchmark_command).await?;
426429
} else {
427430
debug!("No SBT tasks to run.");

build/build/src/enso.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::engine::StandardLibraryTestsSelection;
12
use crate::prelude::*;
23

34
use crate::paths::Paths;
@@ -113,6 +114,7 @@ impl BuiltEnso {
113114
ir_caches: IrCaches,
114115
sbt: &crate::engine::sbt::Context,
115116
async_policy: AsyncPolicy,
117+
test_selection: StandardLibraryTestsSelection,
116118
) -> Result {
117119
let paths = &self.paths;
118120
// Environment for meta-tests. See:
@@ -131,9 +133,22 @@ impl BuiltEnso {
131133
ide_ci::fs::write(google_api_test_data_dir.join("secret.json"), gdoc_key)?;
132134
}
133135

136+
let std_tests = match &test_selection {
137+
StandardLibraryTestsSelection::All =>
138+
crate::paths::discover_standard_library_tests(&paths.repo_root)?,
139+
StandardLibraryTestsSelection::Selected(only) =>
140+
only.iter().map(|test| paths.repo_root.test.join(test)).collect(),
141+
};
142+
let may_need_postgres = match &test_selection {
143+
StandardLibraryTestsSelection::All => true,
144+
StandardLibraryTestsSelection::Selected(only) =>
145+
only.iter().any(|test| test.contains("Postgres_Tests")),
146+
};
147+
134148
let _httpbin = crate::httpbin::get_and_spawn_httpbin_on_free_port(sbt).await?;
149+
135150
let _postgres = match TARGET_OS {
136-
OS::Linux => {
151+
OS::Linux if may_need_postgres => {
137152
let runner_context_string = crate::env::ENSO_RUNNER_CONTAINER_NAME
138153
.get_raw()
139154
.or_else(|_| ide_ci::actions::env::RUNNER_NAME.get())
@@ -156,7 +171,6 @@ impl BuiltEnso {
156171
_ => None,
157172
};
158173

159-
let std_tests = crate::paths::discover_standard_library_tests(&paths.repo_root)?;
160174
let futures = std_tests.into_iter().map(|test_path| {
161175
let command = self.run_test(test_path, ir_caches);
162176
async move { command?.run_ok().await }

build/build/src/libraries_tests.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,17 @@ pub mod s3 {
88
}
99
}
1010
}
11+
12+
pub mod snowflake {
13+
/// Environment variables used inside of the Snowflake tests.
14+
pub mod env {
15+
ide_ci::define_env_var! {
16+
ENSO_SNOWFLAKE_ACCOUNT, String;
17+
ENSO_SNOWFLAKE_USER, String;
18+
ENSO_SNOWFLAKE_PASSWORD, String;
19+
ENSO_SNOWFLAKE_DATABASE, String;
20+
ENSO_SNOWFLAKE_SCHEMA, String;
21+
ENSO_SNOWFLAKE_WAREHOUSE, String;
22+
}
23+
}
24+
}

build/build/src/rust/parser.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ pub async fn run_self_tests(repo_root: &RepoRoot) -> Result {
6969
.output_ok()
7070
.await?
7171
.into_stdout_string()?;
72-
trace!("Generated test code:\n{tests_code}");
7372
ide_ci::fs::tokio::write(&test, tests_code).await?;
7473

7574
Javac

0 commit comments

Comments
 (0)