Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
6a484d4
test: the station protocol tests no longer test serde
jwric Oct 15, 2026
2522fa0
chore: rstest and relative-path are workspace dependencies
jwric Oct 15, 2026
c8ca770
refactor: a job's definition is tracel-job's JobDefinition
jwric Oct 15, 2026
7205dd8
test: the process adapter is tested through execute itself
jwric Oct 15, 2026
95bd166
test: Jobs::prepare and job registration are tested in jobs.rs
jwric Oct 15, 2026
6d0e8f7
test: the execution tests assert only what running a job decides
jwric Oct 15, 2026
befb76c
test: the process adapter tests assert only what the adapter maps
jwric Oct 15, 2026
20e35fc
test: the describe tests leave the definitions file format to tracel-job
jwric Oct 15, 2026
32e349d
test: the job tests assert what preparing a job decides
jwric Oct 15, 2026
167c879
test: nested scopes and failed renames are covered
jwric Oct 15, 2026
622a9f8
fix: one malformed station event no longer ends the session
jwric Oct 15, 2026
84cd3a0
fix: a panic while a station job's input decodes fails the job
jwric Oct 15, 2026
5259669
docs: every public item of tracel-runtime is documented
jwric Oct 15, 2026
b35e86d
fix: a station url that is not http no longer panics the runner
jwric Oct 15, 2026
598e49c
test: the serve tests assert only what the executor reports
jwric Oct 15, 2026
7cd2909
test: the station protocol and SSE tests are named by their outcome
jwric Oct 15, 2026
5bda879
refactor: the station runner loop has no line comments
jwric Oct 15, 2026
adc0aa9
fix: one unresolvable reference no longer removes every flag
jwric Oct 15, 2026
9ee58e0
fix: a bool flag no longer swallows the json input after it
jwric Oct 15, 2026
fc29aea
fix: a field named version gets its flag
jwric Oct 15, 2026
e1681d4
fix: the definitions file gives its program's sdk version
jwric Oct 15, 2026
4ad8609
fix: the definitions file orders its jobs by name
jwric Oct 15, 2026
53e005b
docs: input_example is documented as the job's default input
jwric Oct 15, 2026
ee3f55f
fix: an optional field takes the help of the type it makes optional
jwric Oct 15, 2026
3054fb6
test: cli fixtures are job definitions with distinct descriptions
jwric Oct 15, 2026
52a407f
test: the command tests check what tracel-job decides, not clap
jwric Oct 15, 2026
c851e56
test: cover the schema branches nothing tested
jwric Oct 15, 2026
fa81380
refactor: split the local store into one module per job
jwric Oct 15, 2026
f875278
fix: a local artifact name cannot reach outside its run
jwric Oct 15, 2026
9445fb5
fix: a local experiment name or id is exactly one directory
jwric Oct 15, 2026
1357397
fix: flushing a local run writes the events it recorded
jwric Oct 15, 2026
ae00e15
fix: a local run whose events fail to write ends as failed
jwric Oct 15, 2026
af8e010
fix: a local artifact is replaced only once the new one is written
jwric Oct 15, 2026
009fc4d
test: pin the runs gitignore and numbering under contention
jwric Oct 15, 2026
96abe07
test: the local status test checks only what the store decides
jwric Oct 15, 2026
acdbb71
test: a local artifact never saved does not load
jwric Oct 15, 2026
b1766e6
style: drop the line comment in Experiments::run
jwric Oct 15, 2026
32f5482
test: each start hook is shown the run it was called with
jwric Oct 15, 2026
f8b4485
test: split the started-arguments test into the two rules it pins
jwric Oct 15, 2026
f80a6b8
test: provider tests match the panic reason's end and use a plain flag
jwric Oct 15, 2026
49b4219
test: a cancelled run keeps logging after its stop warning
jwric Oct 15, 2026
f54c2b4
fix: TRACEL_ENV takes only digits as a staging number
jwric Oct 15, 2026
b28e64e
test: target tests assert only what can fail
jwric Oct 15, 2026
91244f6
feat: console settings can be read without the process environment
jwric Oct 15, 2026
fa1f0cc
fix: an unreadable or malformed tracel.toml is an error naming it
jwric Oct 15, 2026
4a12e59
docs: the job command line docs match the generated flags
jwric Oct 15, 2026
0e94e81
fix: a console target reports a missing setting as the console does
jwric Oct 15, 2026
7f41fd3
fix: a console target's services share one console connection
jwric Oct 15, 2026
65b6263
fix: an artifact name several artifacts share loads the newest
jwric Oct 15, 2026
5e42946
test: experiments are linked to a job through the runtime's own seam
jwric Oct 15, 2026
bff2c41
docs: the crates name their registries instead of capabilities
jwric Oct 15, 2026
2d6af69
test: the example bundle decodes without an empty metadata check
jwric Oct 15, 2026
833366c
docs: the README says TRACEL_TARGET=station needs the station feature
jwric Oct 15, 2026
ef550ad
ci: lint and tests build the station, burn and schema features
jwric Oct 15, 2026
5bc4240
refactor: the process reads its launch variables once, in Jobs::run
jwric Oct 15, 2026
4c398ea
test: an exit code reads back from its code, one case per code
jwric Oct 15, 2026
4e82431
test: the definitions file tests no longer test serde
jwric Oct 15, 2026
0846456
test: the flags tests check one rule each, as rstest cases
jwric Oct 15, 2026
38b6478
test: target tests assert the target or error each variable gives
jwric Oct 15, 2026
94a47e1
fix: a station target's services share one station
jwric Oct 15, 2026
ae1d380
test: console settings tests assert outcomes, not messages
jwric Oct 15, 2026
df6a502
test: console tests no longer read the connection's private state
jwric Oct 15, 2026
d8d2414
test: dataset upload tests check what is sent, not the constants
jwric Oct 15, 2026
a91beb4
test: inference telemetry tests check what reaches the console
jwric Oct 15, 2026
7770378
test: a job number's attribute value is tested by case
jwric Oct 15, 2026
76a68f6
docs: the runtime's docs say outside a job, not in a unit test
jwric Oct 15, 2026
200b719
test: the panic tests assert the failure, not its message
jwric Oct 15, 2026
c8872d5
test: each scope test checks one rule against the scope it entered
jwric Oct 15, 2026
6d2e052
test: how a job ends is one rstest case per outcome
jwric Oct 15, 2026
b2379f5
test: the job tests build their expectations from the fixture
jwric Oct 15, 2026
590a170
test: each write_atomically test checks one rule
jwric Oct 15, 2026
feb9849
test: the process test helpers carry no doc comments
jwric Oct 15, 2026
93641a8
test: describe is not tested for the file serde writes
jwric Oct 15, 2026
2e67871
test: the cancelled job test compares the statuses reported
jwric Oct 15, 2026
e88a5bd
test: the SSE tests compare whole frames
jwric Oct 15, 2026
9a68d9f
test: the run numbering test checks only the numbers
jwric Oct 15, 2026
9ab3203
test: the status tests check how a run ended, not its JSON
jwric Oct 15, 2026
9b906a6
test: the events lines are not tested for the JSON serde writes
jwric Oct 15, 2026
30e3416
test: a saved artifact loads back from a run of the fixture's store
jwric Oct 15, 2026
b735bbd
test: activity endings and progress are tested beside the activity
jwric Oct 15, 2026
2228530
test: the panic watch is tested in its own module
jwric Oct 15, 2026
f4bea28
test: a record's own attribute winning is tested on the record
jwric Oct 15, 2026
baa41a2
test: run tests assert one outcome each, with rstest cases
jwric Oct 15, 2026
ba37671
test: provider tests take an rstest fixture and assert one outcome
jwric Oct 15, 2026
7d28cf9
test: each ambient scope rule has a test of its own
jwric Oct 15, 2026
5165701
test: each run control test checks one outcome
jwric Oct 15, 2026
cbdd1a4
test: a token cancels each child once, counted by the child
jwric Oct 15, 2026
b0fb0d9
test: the tracing layer's rules are tested in its own module
jwric Oct 15, 2026
ef5a514
test: the progress loggers are tested one rule at a time
jwric Oct 15, 2026
eac7fad
refactor: an experiment run no longer has a location or announces itself
jwric Oct 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ name: CI

env:
CARGO_TERM_COLOR: always
FEATURES: tracel/station,tracel/burn,tracel/schema

# For now we execute CI only on PR to save on CI time
on:
Expand Down Expand Up @@ -33,16 +34,16 @@ jobs:
run: cargo xtask check format
# --------------------------------------------------------------------------------
- name: Lint
run: cargo xtask check lint
run: cargo xtask check --features "$FEATURES" lint
# --------------------------------------------------------------------------------
- name: Typos
uses: tracel-ai/github-actions/check-typos@v11
# --------------------------------------------------------------------------------
- name: Unit Tests
run: cargo xtask test unit
run: cargo xtask test --features "$FEATURES" unit
# --------------------------------------------------------------------------------
- name: Integration Tests
run: cargo xtask test integration
run: cargo xtask test --features "$FEATURES" integration
# --------------------------------------------------------------------------------
- name: Documentation Tests
run: cargo xtask doc tests
run: cargo xtask doc --features "$FEATURES" tests
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ categories = ["development-tools"]
burn = { version = "0.22", default-features = false, features = [ "train" ] }

rand = "0.9.2"
relative-path = "1.9.3"
rstest = "0.27.0"
tempfile = "3.27.0"

url = "2.5.8"
Expand Down
15 changes: 7 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,8 @@ input, merged onto its default, as its arguments, which the console lists as its

The experiments `Target::experiments` builds in a job, on the thread that runs it, are linked to
that job, even for runs started on other threads: each one started from them records the job's
number and input, and prints where it records to stderr as it starts, such as
`Recording experiment 42: <url>`, which `tracel run` and a remote job's logs show. Experiments
built another way, such as `ProjectHandle::experiments`, are not linked unless the code links
them, through `Experiments::attribute`, `arguments` and `on_start`.
number and input. Experiments built another way, such as `ProjectHandle::experiments`, are not
linked unless the code links them, through `Experiments::attribute` and `arguments`.

The [`cli`](examples/basics/examples/cli.rs) example in [`examples/basics`](examples/basics) is a
complete, runnable version.
Expand All @@ -103,7 +101,7 @@ complete, runnable version.

| Variable | Value | Default |
| --- | --- | --- |
| `TRACEL_TARGET` | `offline` or `console` | `offline` |
| `TRACEL_TARGET` | `offline`, `console`, or `station` with the `station` feature of `tracel` | `offline` |
| `TRACEL_RUNS_DIR` | the directory offline runs are recorded under | `./runs` |
| `TRACEL_ENV` | the console to reach | `Production` |
| `TRACEL_API_KEY` | an API key or a job token | the stored `tracel login` session |
Expand Down Expand Up @@ -159,11 +157,12 @@ Options:
- A nested field's flag joins the keys with dots and writes `_` as `-`: the field
`optimizer.weight_decay` is `--optimizer.weight-decay`. A field that is an array, a map, an
optional object or an enum with data takes a JSON literal, such as `--layers '[64, 32]'`. A
boolean flag given no value is `true`.
boolean flag given no value is `true`, and takes a value only as `--flag=value`, such as
`--shuffle=false`.
- The input is the default input, then the `--config` file, then the JSON document, then the
flags, each merged onto the one before, so a later one wins. Launchers pass the JSON document.
- `help`, `version` and `config` are the command line's names: a field with one of them has no
flag, and is set through `--config` or the JSON document.
- `help` and `config` are the command line's names: a field with one of them has no flag, and is
set through `--config` or the JSON document.
- `--completions <SHELL>` prints the completion script for `bash`, `elvish`, `fish`, `powershell`
or `zsh`: `cargo run -- --completions bash > cli.bash`.

Expand Down
12 changes: 0 additions & 12 deletions crates/tracel-artifact/src/bundle/memory/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,18 +96,6 @@ impl BundleDecode for ExampleConfig {
let config: ExampleConfig = serde_json::from_str(&config_content)
.map_err(|e| format!("Failed to parse config JSON: {}", e))?;

// Optionally validate metadata exists (but don't require it for decoding)
if let Ok(mut metadata_reader) = source.open(&settings.metadata_filename) {
let mut metadata_content = String::new();
if metadata_reader
.read_to_string(&mut metadata_content)
.is_ok()
&& let Ok(_metadata) = serde_json::from_str::<ConfigMetadata>(&metadata_content)
{
// Could validate version compatibility here
}
}

Ok(config)
}
}
Expand Down
4 changes: 4 additions & 0 deletions crates/tracel-console/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,7 @@ tracel-experiment-remote = { workspace = true }
tracel-inference = { workspace = true }
tracel-models = { workspace = true }
url = { workspace = true }

[dev-dependencies]
rstest = { workspace = true }
tempfile = { workspace = true }
66 changes: 28 additions & 38 deletions crates/tracel-console/src/console.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
use std::ffi::OsString;
use std::fmt;
use std::path::Path;
use std::sync::{Arc, Mutex, OnceLock, PoisonError};
use std::time::{Duration, SystemTime};

use tracel_artifact::ReqwestTransferClient;
use tracel_client::{
ClientError,
console::{Client, Env, TracelCredentials, user::response::UserResponseSchema},
console::{
Client, Env, FileSessionStore, SessionStoreError, TracelCredentials,
user::response::UserResponseSchema,
},
};
use tracel_datasets::DatasetRegistry;
use tracel_experiment::Experiments;
Expand All @@ -14,7 +19,7 @@ use tracel_models::ModelRegistry;
use url::Url;

use crate::datasets::ConsoleDatasetOps;
use crate::env::{CredentialSource, ProjectRef, env_from_environment};
use crate::env::{CredentialSource, ProjectRef, env_from_environment, env_from_vars};
use crate::experiment::ConsoleExperimentProvider;
use crate::inference::ConsoleInferenceProvider;
use crate::models::ConsoleModelOps;
Expand Down Expand Up @@ -92,8 +97,6 @@ pub struct ProjectScope {
console: Console,
pub owner: String,
pub project: String,
/// The kind of namespace that owns the project, once read from the console.
owner_kind: OnceLock<NamespaceKind>,
}

impl ProjectScope {
Expand All @@ -111,19 +114,9 @@ impl ProjectScope {
pub fn fetch(&self) -> Result<Project, ConsoleError> {
let project = self.client()?.get_project(&self.owner, &self.project)?;
let project = Project::try_from(project)?;
let _ = self.owner_kind.set(project.namespace.kind);
Ok(project)
}

/// Returns the kind of namespace that owns the project, fetching the project on the first
/// call.
pub fn owner_kind(&self) -> Result<NamespaceKind, ConsoleError> {
match self.owner_kind.get() {
Some(kind) => Ok(*kind),
None => self.fetch().map(|project| project.namespace.kind),
}
}

/// Returns the client that moves files to and from presigned URLs.
pub fn transfer_client(&self) -> &ReqwestTransferClient {
&self.console.inner.transfer_client
Expand Down Expand Up @@ -236,7 +229,6 @@ impl Console {
console: self.clone(),
owner: owner.into(),
project: project.into(),
owner_kind: OnceLock::new(),
}),
}
}
Expand Down Expand Up @@ -301,11 +293,28 @@ impl ProjectHandle {
/// The owner namespace is `TRACEL_NAMESPACE` and the project name `TRACEL_PROJECT`; either
/// one unset is read from `namespace` or `project` in `tracel.toml` in the current
/// directory. Fails with [`ConsoleError::NoNamespace`] or [`ConsoleError::NoProject`] when
/// neither names it.
/// neither names it, and with [`ConsoleError::InvalidTracelToml`] when `tracel.toml`
/// cannot be read.
pub fn from_env() -> Result<Self, ConsoleError> {
let console = Console::from_env()?;
let project = ProjectRef::from_env()?;
Ok(console.project(project.namespace, project.name))
Self::from_vars(
|name| std::env::var_os(name),
Path::new("."),
FileSessionStore::for_server,
)
}

/// [`from_env`](Self::from_env), reading the variables from `lookup`, `tracel.toml` from
/// `dir`, and the stored `tracel login` session from the store `sessions` gives for the
/// console's URL.
pub fn from_vars(
lookup: impl Fn(&str) -> Option<OsString>,
dir: &Path,
sessions: impl FnOnce(&Url) -> Result<FileSessionStore, SessionStoreError>,
) -> Result<Self, ConsoleError> {
let env = env_from_vars(&lookup)?;
let credentials = CredentialSource::from_vars(&lookup).resolve_with(&env, sessions)?;
let project = ProjectRef::from_vars(&lookup, dir)?;
Ok(Console::connect(env, credentials).project(project.namespace, project.name))
}

/// Returns the console this project is reached through.
Expand Down Expand Up @@ -385,23 +394,4 @@ mod tests {
assert_send_sync::<Console>();
assert_send_sync::<ProjectHandle>();
}

#[test]
fn binding_and_scoping_send_no_request() {
let console = Console::connect(
Env::Development,
TracelCredentials::api_key("tcl_key_not_checked_until_the_first_request"),
);
let project = console.project("owner", "project");
let _ = (
project.datasets(),
project.models(),
project.experiments(),
project.inference(),
);

assert!(console.inner.connected.get().is_none());
assert!(Arc::ptr_eq(&project.console().inner, &console.inner));
assert_eq!(console.base_url(), &Env::Development.get_url());
}
}
Loading
Loading