Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 10 additions & 0 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"permissions": {
"allow": [
"Bash(rg:*)",
"Bash(grep:*)",
"Bash(npm run compile:*)"
],
"deny": []
}
}
14 changes: 7 additions & 7 deletions .github/workflows/build-extensions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ jobs:
- name: Build theme extension
run: |
echo "Building theme extension..."
cd themes && npx @vscode/vsce package --out ../zenml-color-theme.vsix
cd themes && npx @vscode/vsce package --out ./zenml-color-theme-0.0.1.vsix

- name: Verify extensions were built
- name: Verify extensions were builts
run: |
echo "Checking built extensions..."
if [ -d ".devcontainer/extensions" ]; then
Expand All @@ -54,11 +54,11 @@ jobs:
exit 1
fi

if [ -f "zenml-color-theme.vsix" ]; then
if [ -f "themes/zenml-color-theme-0.0.1.vsix" ]; then
echo "Theme extension built successfully:"
ls -la zenml-color-theme.vsix
ls -la themes/zenml-color-theme-0.0.1.vsix
else
echo "ERROR: zenml-color-theme.vsix not found"
echo "ERROR: zenml-color-theme-0.0.1.vsix not found"
exit 1
fi

Expand All @@ -72,7 +72,7 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: theme-extension
path: zenml-color-theme.vsix
path: themes/zenml-color-theme-0.0.1.vsix

- name: Commit and push built extensions
# Only commit on push to main/develop branches, not on PRs
Expand All @@ -83,7 +83,7 @@ jobs:

# Add the built extensions to git
git add .devcontainer/extensions/zenml-codespace-tutorial-*.vsix
git add zenml-color-theme.vsix
git add themes/zenml-color-theme-0.0.1.vsix

# Check if there are any changes to commit
if git diff --staged --quiet; then
Expand Down
57 changes: 56 additions & 1 deletion assets/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ header {
}

.tutorial-title h2 {
font-size: 1rem;
font-size: 1.25rem;
font-weight: 600;
color: var(--zenml-dark);
margin: 0;
Expand Down Expand Up @@ -448,13 +448,68 @@ footer .run-pipeline-button.running {
footer .run-pipeline-button.completed {
background: var(--zenml-green);
color: white;
cursor: default;
}

footer .run-pipeline-button.completed:hover {
background: var(--zenml-green);
transform: none;
box-shadow: none;
}

footer .run-pipeline-button.failed {
background: var(--zenml-red);
color: white;
}


/* Pipeline button group */
.pipeline-button-group {
display: flex;
gap: 8px;
align-items: center;
}

/* Dashboard button styling - smaller variant */
.dashboard-button-small {
background: var(--vscode-button-secondaryBackground);
border: 1px solid var(--vscode-sideBar-border);
color: var(--vscode-button-secondaryForeground);
padding: 9px 16px;
border-radius: 6px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 6px;
justify-content: center;
font-family: "Inter", sans-serif;
margin: 0;
height: 38px;
text-decoration: none;
flex-shrink: 0;
white-space: nowrap;
box-sizing: border-box;
}

.dashboard-button-small:hover {
background: var(--vscode-button-secondaryHoverBackground);
transform: translateY(-1px);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
color: var(--vscode-button-secondaryForeground);
text-decoration: none;
}

.dashboard-button-small:active {
transform: translateY(0);
}

.dashboard-button-small .codicon {
font-size: 14px;
}

#progress {
height: 4px;
background-color: var(--vscode-progressBar-background);
Expand Down
19 changes: 12 additions & 7 deletions assets/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,8 @@
} else if (status === "completed" || status === "cached") {
runButton.innerHTML = `<i class="checkmark">✓</i> ${buttonTexts[status]}`;
//@ts-ignore
runButton.disabled = false;
runButton.disabled = true;
runButton.style.cursor = "default";
} else if (status === "failed") {
runButton.innerHTML = `<i class="codicon codicon-error"></i> ${buttonTexts[status]}`;
//@ts-ignore
Expand All @@ -493,14 +494,18 @@
}

function showDashboardUrl(url) {
const dashboardLink = document.getElementById("dashboard-link");
const dashboardUrl = document.getElementById("dashboard-url");
const dashboardButton = document.getElementById("dashboard-button");

if (dashboardLink && dashboardUrl) {
if (dashboardButton) {
//@ts-ignore
dashboardUrl.href = url;
dashboardUrl.textContent = "View Pipeline in Dashboard";
dashboardLink.style.display = "flex";
dashboardButton.href = url;
dashboardButton.style.display = "flex";

// Add click handler to open in external browser
dashboardButton.addEventListener('click', function(e) {
e.preventDefault();
vscode.postMessage({ type: "openDashboard", url: url });
});
}
}

Expand Down
20 changes: 13 additions & 7 deletions pipelines/caching/cache_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@

@step(enable_cache=True)
def slow_step() -> Annotated[int, "answer"]:
logger.info("Starting slow computation (3 seconds)...")
logger.info("🔄 Actually computing result... (sleeping 3 seconds)")
time.sleep(3)
logger.info("Computation completed!")
return 42


Expand All @@ -23,10 +22,17 @@ def cache_pipeline():


if __name__ == "__main__":
logger.info("First run - will take ~3 seconds")
cache_pipeline() # first run ~3 s

logger.info("Second run - should be instant (cache hit)")
cache_pipeline() # second run instant (cache hit)
logger.info("\n" + "="*60)
logger.info(">>> RUN 1: First execution (no cache available)")
logger.info("="*60)
cache_pipeline()

logger.info("\n" + "="*60)
logger.info(">>> RUN 2: Second execution (cache should be used)")
logger.info("="*60)
cache_pipeline()

logger.info("\n💡 Notice: The step's log message only appears in Run 1!")
logger.info(" In Run 2, the step was skipped entirely due to caching.")

log_dashboard_urls("cache_pipeline")
7 changes: 2 additions & 5 deletions pipelines/caching/caching.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
# Caching - Smart Re-runs

Learn how ZenML's caching system can save you time by avoiding redundant computations.

## What you'll learn

- How to enable caching on steps
Expand All @@ -28,4 +24,5 @@ def slow_step() -> Annotated[int, "answer"]:

## Try it yourself

Run this pipeline twice! The first run takes ~3 seconds, the second is instant thanks to caching.
Run this pipeline twice! The first run takes ~3 seconds, the second is instant
thanks to caching.
2 changes: 1 addition & 1 deletion pipelines/completion/completion.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

You Completed the Tutorial

You've successfully completed the **ZenML Interactive Tutorial** and mastered the fundamentals of MLOps with ZenML!
You've successfully completed the **ZenML Interactive Tutorial** and mastered the fundamentals of using ZenML for MLOps!

</div>
<div class="right-column">
Expand Down
7 changes: 2 additions & 5 deletions pipelines/fanOut/fanOut.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
# Fan-out/Fan-in - Parallel Processing

Learn how to create parallel workflows that split work across multiple steps and then combine the results.

## What you'll learn

- How to create parallel processing patterns
Expand Down Expand Up @@ -29,4 +25,5 @@ def fan_pipeline(parallel: int = 4):

## Try it yourself

Run this pipeline to see how it processes data in parallel across multiple steps, then combines the results!
Run this pipeline to see how it processes data in parallel across multiple
steps, then combines the results!
8 changes: 0 additions & 8 deletions pipelines/fanOut/fan_pipeline.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
"""
Shows parallel fan-out (multiple identical steps) and a fan-in step that
gathers all their outputs via the Client API.

Run it once and observe the printed summary. Re-run: cache is OFF so you
see the steps execute every time.
"""

from typing_extensions import Annotated
from zenml import get_step_context, pipeline, step
from zenml.client import Client
Expand Down
5 changes: 2 additions & 3 deletions pipelines/helloWorld/helloWorld.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# Hello World - Steps & Pipelines

Welcome to your first ZenML pipeline! This tutorial introduces the fundamental concepts of **steps** and **pipelines**.

## What you'll learn
Expand Down Expand Up @@ -30,4 +28,5 @@ def hello_pipeline():

## Try it yourself

Click the **Run Pipeline** button to execute your first ZenML pipeline and see the output!
Click the **Run Pipeline** button to execute your first ZenML pipeline and see
the output!
6 changes: 1 addition & 5 deletions pipelines/metadata/metadata.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
# Metadata - Recording Useful Facts

Learn how to log metadata to track important information about your pipeline runs.

## What you'll learn

- How to use `log_metadata()` to record key information
Expand Down Expand Up @@ -29,4 +25,4 @@ def compute_accuracy() -> Annotated[float, "accuracy_metric"]:

## Try it yourself

Run this pipeline and check the ZenML dashboard to see the metadata card!
Run this pipeline and check the ZenML dashboard to see the metadata card!
6 changes: 1 addition & 5 deletions pipelines/parameters/parameters.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
# Parameters - Configurable Behavior

Learn how to make your pipelines configurable with parameters.

## What you'll learn

- How to add parameters to steps and pipelines
Expand Down Expand Up @@ -31,4 +27,4 @@ def param_pipeline(number: int = 3, factor: int = 2):

## Try it yourself

Run this pipeline to see how parameters control the multiplication operation!
Run this pipeline to see how parameters control the multiplication operation!
7 changes: 2 additions & 5 deletions pipelines/retries/retries.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
# Retries & Hooks - Robust Pipelines

Learn how to build resilient pipelines that can handle failures gracefully with automatic retries and hooks.

## What you'll learn

- How to configure automatic retries for flaky steps
Expand Down Expand Up @@ -32,4 +28,5 @@ def flaky() -> Annotated[str, "result"]:

## Try it yourself

Run this pipeline multiple times! Sometimes it succeeds immediately, sometimes it needs retries to handle the random failures.
Run this pipeline multiple times! Sometimes it succeeds immediately, sometimes
it needs retries to handle the random failures.
5 changes: 0 additions & 5 deletions pipelines/retries/robust_pipeline.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
"""
Demonstrates automatic retries *and* a failure hook.
Run it a few times – roughly half will need 1–2 retries.
"""

import random
import time

Expand Down
7 changes: 2 additions & 5 deletions pipelines/stepIO/stepIO.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
# Step I/O - Typed Inputs and Outputs

Now let's learn how to pass data between steps with proper type annotations.

## What you'll learn

- How to define typed step outputs using `Annotated` types
Expand Down Expand Up @@ -37,4 +33,5 @@ def count_rows(

## Try it yourself

Run this pipeline to see how data flows from the `load_data` step to the `count_rows` step!
Run this pipeline to see how data flows from the `load_data` step to the
`count_rows` step!
9 changes: 0 additions & 9 deletions pipelines/tagging/tagged_pipeline.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,3 @@
"""
Artifact Tagging Demonstration
This example shows different ways to tag artifacts in ZenML:
1. Regular tags on artifacts using ArtifactConfig
2. Cascade tags from pipeline to artifacts
3. Dynamic tagging within steps
4. Filtering artifacts by tags
"""

from typing import Annotated

import pandas as pd
Expand Down
7 changes: 2 additions & 5 deletions pipelines/tagging/tagging.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
# Tagging - Keep Runs Organized

Learn how to use tags to organize and categorize your pipeline runs.

## What you'll learn

- How to add simple tags to pipelines
Expand All @@ -27,4 +23,5 @@ def tagged_pipeline():

## Try it yourself

Run this pipeline multiple times and watch how the exclusive tag automatically moves to the latest run!
Run this pipeline multiple times and watch how the exclusive tag automatically
moves to the latest run!
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 4 additions & 5 deletions pipelines/visualizations/visualizations.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
# Visualizations - Custom Charts

Learn how to create automatic and custom visualizations that appear in the ZenML dashboard.

## What you'll learn

- How ZenML automatically visualizes common data types
Expand Down Expand Up @@ -30,6 +26,9 @@ def scatter(df: pd.DataFrame) -> Annotated[HTMLString, "scatter_plot"]:
- **HTMLString type** lets you embed rich content in the dashboard
- **Dashboard integration** makes results easily shareable

![Two visualizations generated by this pipeline](./pipelines/visualizations/visualizations-dashboard.png)

## Try it yourself

Run this pipeline and check the dashboard to see both the automatic DataFrame visualization and the custom scatter plot!
Run this pipeline and check the dashboard to see both the automatic DataFrame
visualization and the custom scatter plot!
2 changes: 1 addition & 1 deletion pipelines/welcome/welcome.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div class="two-column-content">
<div class="left-column">

# Welcome to ZenML Interactive Tutorial!
# Welcome to the ZenML Interactive Tutorial!

This hands-on tutorial will teach you **ZenML fundamentals** through 10 progressive lessons. Each lesson introduces exactly **one new concept** with copy-paste code examples.

Expand Down
Loading
Loading