-
Notifications
You must be signed in to change notification settings - Fork 8
Add test to execute notebooks #58
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
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,11 @@ on: | |
| description: "Pull request number or branch name" | ||
| required: true | ||
| default: "main" | ||
| pull_request: | ||
| types: [opened, synchronize, reopened] | ||
| paths: | ||
| - "notebooks/**/*.ipynb" | ||
| - ".github/workflows/execute-all-notebooks.yml" | ||
|
|
||
| env: | ||
| INSTANCE_TYPE: "g6e.xlarge" | ||
|
|
@@ -70,6 +75,26 @@ jobs: | |
| run: | | ||
| echo "hello. i'm running from inside of EC2 instance ${{ needs.launch-ec2-runner.outputs.ec2-instance-id }}" | ||
|
|
||
| - uses: actions/checkout@v5 | ||
|
|
||
| - name: Set up Python | ||
| uses: actions/setup-python@v6 | ||
| with: | ||
| python-version: "3.12" | ||
| cache: pip | ||
|
|
||
| - name: Install Dependencies | ||
| run: | | ||
| pip install -r requirements-dev.txt | ||
| pip install papermill ipykernel jupyter | ||
| ipython kernel install --name "python3" --user | ||
|
|
||
|
Comment on lines
+86
to
+91
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. 🧩 Analysis chainPotential dependency version conflicts from dual installation. Installing from 🏁 Script executed: #!/bin/bash
# Check if papermill, ipykernel, or jupyter are already in requirements-dev.txt
echo "=== Checking requirements-dev.txt for potential conflicts ==="
if [ -f requirements-dev.txt ]; then
echo "File exists. Checking for papermill, ipykernel, jupyter..."
grep -E "(papermill|ipykernel|jupyter)" requirements-dev.txt || echo "None found in requirements-dev.txt"
else
echo "requirements-dev.txt not found"
fiLength of output: 130 🏁 Script executed: #!/bin/bash
# Get full requirements-dev.txt and check papermill line + context
echo "=== Full requirements-dev.txt content ==="
cat requirements-dev.txt
echo ""
echo "=== Workflow file lines 86-95 for context ==="
sed -n '86,95p' .github/workflows/execute-all-notebooks.ymlLength of output: 482 Remove redundant papermill installation to ensure consistent dependency resolution. Papermill is already specified in 🤖 Prompt for AI Agents |
||
| - name: Execute All Notebooks via Pytest | ||
| run: | | ||
| cd tests | ||
| python -m pytest test_notebook_execution.py -v --tb=short | ||
|
|
||
|
|
||
| stop-ec2-runner: | ||
| permissions: | ||
| id-token: write # This is required for OIDC (AWS auth) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| """ | ||
| Simple notebook execution tests for CI/CD integration. | ||
| This module provides basic notebook execution testing using papermill, | ||
| designed to be lightweight and integrate easily with GitHub Actions. | ||
| """ | ||
|
|
||
| import os | ||
| import tempfile | ||
| from pathlib import Path | ||
|
|
||
| import papermill as pm | ||
|
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. 🧩 Analysis chainVerify papermill dependency is declared in requirements. Ensure that 🏁 Script executed: #!/bin/bash
# Check if papermill is declared in requirements files
echo "=== Checking for papermill in requirements files ==="
fd -t f "requirements.*\.txt$" --exec grep -H "papermill" {} \;
echo ""
echo "=== Checking for ipykernel in requirements files ==="
fd -t f "requirements.*\.txt$" --exec grep -H "ipykernel" {} \;
echo ""
echo "=== Listing all requirements files ==="
fd -t f "requirements.*\.txt$"Length of output: 343 I need to verify whether Now let me check if there are other dependency declaration files in the repo: Let me check the project's own dependency declarations: 🏁 Script executed: #!/bin/bash
# Check for setup.py and pyproject.toml in the project root
echo "=== Checking for setup.py ==="
fd -t f "setup.py" --max-depth 1
echo ""
echo "=== Checking for pyproject.toml ==="
fd -t f "pyproject.toml" --max-depth 1
echo ""
echo "=== Checking contents of requirements-dev.txt ==="
cat requirements-dev.txtLength of output: 170 Let me re-run the script with proper repository access: 🏁 Script executed: #!/bin/bash
# Check for setup.py and pyproject.toml in the project root
echo "=== Checking for setup.py ==="
fd -t f "setup.py" --max-depth 1
echo ""
echo "=== Checking for pyproject.toml ==="
fd -t f "pyproject.toml" --max-depth 1
echo ""
echo "=== Checking contents of requirements-dev.txt ==="
cat requirements-dev.txt
echo ""
echo "=== Checking if ipykernel is a transitive dependency of papermill ==="
grep -E "^(jupyter|nbclient|ipykernel)" requirements-dev.txt || echo "Not explicitly listed in requirements-dev.txt"Length of output: 290 Let me check the pyproject.toml and verify papermill's dependencies: 🏁 Script executed: #!/bin/bash
# Check pyproject.toml contents and look for dependency sections
echo "=== Contents of pyproject.toml ==="
cat pyproject.toml
echo ""
echo "=== Checking test dependencies in pyproject.toml ==="
grep -A 20 "\[project.optional-dependencies\]" pyproject.toml || echo "No optional dependencies found"Length of output: 1013 🌐 Web query: 💡 Result: Short answer
Details / recommended installs
Useful references
Now let me check what the test file actually does to determine if ipykernel is needed: 🏁 Script executed: #!/bin/bash
# Check what the test file actually does
echo "=== Contents of tests/test_notebook_execution.py ==="
cat tests/test_notebook_execution.pyLength of output: 3008 Add The test file executes notebooks using 🤖 Prompt for AI Agents |
||
| import pytest | ||
|
|
||
| from conftest import get_notebook_files | ||
|
|
||
|
|
||
| def get_test_parameters(): | ||
| """Get default test parameters for notebook execution.""" | ||
| return { | ||
| "files": [], # Empty files list for basic testing | ||
| "test_mode": True, | ||
| "quick_run": True, | ||
| } | ||
|
|
||
|
|
||
| def execute_single_notebook(notebook_path: Path, timeout: int = 300) -> bool: | ||
| """ | ||
| Execute a single notebook with papermill. | ||
| Args: | ||
| notebook_path: Path to notebook to execute | ||
| timeout: Execution timeout in seconds | ||
| Returns: | ||
| True if successful, raises exception if failed | ||
| """ | ||
| with tempfile.NamedTemporaryFile(suffix='.ipynb', delete=False) as tmp_file: | ||
| output_path = Path(tmp_file.name) | ||
|
|
||
| try: | ||
| pm.execute_notebook( | ||
| input_path=str(notebook_path), | ||
| output_path=str(output_path), | ||
| parameters=get_test_parameters(), | ||
| timeout=timeout, | ||
| kernel_name="python3" | ||
| ) | ||
| return True | ||
| except Exception as e: | ||
| raise Exception(f"Notebook execution failed: {str(e)}") from e | ||
| finally: | ||
| if output_path.exists(): | ||
| output_path.unlink() | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("notebook_path", get_notebook_files()) | ||
| def test_notebook_executes_without_error(notebook_path): | ||
| """Test that each notebook executes without errors.""" | ||
|
|
||
| # Skip backup/duplicate files | ||
| if any(skip in str(notebook_path) for skip in ["copy.ipynb", ".checkpoint"]): | ||
| pytest.skip(f"Skipping backup/checkpoint file: {notebook_path}") | ||
|
|
||
| # Execute the notebook | ||
| success = execute_single_notebook(notebook_path, timeout=300) | ||
| assert success, f"Failed to execute notebook: {notebook_path}" | ||
|
|
||
|
|
||
| def test_notebooks_directory_exists(): | ||
| """Verify the notebooks directory exists and contains files.""" | ||
| notebooks = get_notebook_files() | ||
| assert len(notebooks) > 0, "No notebook files found in notebooks directory" | ||
|
|
||
| for notebook in notebooks: | ||
| assert notebook.exists(), f"Notebook file does not exist: {notebook}" | ||
| assert notebook.suffix == '.ipynb', f"File is not a notebook: {notebook}" | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| # Allow running directly for testing | ||
| import sys | ||
|
|
||
| if len(sys.argv) > 1: | ||
| notebook_file = Path(sys.argv[1]) | ||
| if notebook_file.exists(): | ||
| print(f"Testing {notebook_file}...") | ||
| try: | ||
| execute_single_notebook(notebook_file) | ||
| print("✅ Success!") | ||
| except Exception as e: | ||
| print(f"❌ Failed: {e}") | ||
| sys.exit(1) | ||
| else: | ||
| print("Usage: python test_notebook_execution.py <notebook_path>") | ||
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.
Checkout action version inconsistency.
Line 78 uses
actions/checkout@v5, but line 40 usesactions/checkout@v4. Maintain consistency across the workflow by upgrading line 78 to@v5or downgrading line 40 to@v4(preferably keep both on the latest stable version).🤖 Prompt for AI Agents