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
72 changes: 72 additions & 0 deletions .github/workflows/CI.yml → .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,77 @@ permissions:
contents: read

jobs:
test:
name: Test Python ${{ matrix.python-version }}
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.12"]
steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
version: "latest"

- name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy

- name: Install dependencies
run: |
uv sync --dev
uv run maturin develop

- name: Run Rust tests
run: cargo test --verbose

- name: Run Python tests
run: uv run pytest --verbose --tb=short

lint:
name: Code Quality
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
version: "latest"

- name: Set up Python
run: uv python install 3.12

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy

- name: Install dependencies
run: |
uv sync --dev
uv run maturin develop

- name: Check Rust formatting
run: cargo fmt --all -- --check

- name: Run Rust clippy
run: cargo clippy --all-targets --all-features -- -D warnings

- name: Check Python formatting
run: uv run ruff format --check .

- name: Run Python linting
run: uv run ruff check .
linux:
runs-on: ${{ matrix.platform.runner }}
needs: [test, lint]
strategy:
matrix:
platform:
Expand Down Expand Up @@ -56,6 +125,7 @@ jobs:

windows:
runs-on: ${{ matrix.platform.runner }}
needs: [test, lint]
strategy:
matrix:
platform:
Expand Down Expand Up @@ -83,6 +153,7 @@ jobs:

macos:
runs-on: ${{ matrix.platform.runner }}
needs: [test, lint]
strategy:
matrix:
platform:
Expand All @@ -109,6 +180,7 @@ jobs:

sdist:
runs-on: ubuntu-latest
needs: [test, lint]
steps:
- uses: actions/checkout@v4
- name: Build sdist
Expand Down
48 changes: 48 additions & 0 deletions .github/workflows/claude.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Claude PR Assistant

on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]

jobs:
claude-code-action:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && contains(github.event.issue.body, '@claude'))
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Run Claude PR Action
uses: anthropics/claude-code-action@beta
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
# Or use OAuth token instead:
# claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
timeout_minutes: "60"
# mode: tag # Default: responds to @claude mentions
# Optional: Restrict network access to specific domains only
# experimental_allowed_domains: |
# .anthropic.com
# .github.com
# api.github.com
# .githubusercontent.com
# bun.sh
# registry.npmjs.org
# .blob.core.windows.net
61 changes: 61 additions & 0 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Security

on:
push:
branches: [main, master]
pull_request:
schedule:
# Run weekly security scans
- cron: '0 2 * * 1'
workflow_dispatch:

jobs:
security:
name: Security Scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Run Rust security audit
uses: rustsec/audit-check@v1.4.1
with:
token: ${{ secrets.GITHUB_TOKEN }}

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
version: "latest"

- name: Set up Python
run: uv python install 3.12

- name: Install dependencies
run: uv sync --dev

- name: Run Python security scan
run: |
uv add --dev safety
uv run safety check --ignore 70612
continue-on-error: true # Don't fail CI on security advisories, just report

codeql:
name: CodeQL Analysis
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: python

- name: Autobuild
uses: github/codeql-action/autobuild@v3

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
47 changes: 47 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Changed
- Updated `cel-interpreter` from 0.9.0 to 0.10.0

### Added
- **Automatic Type Coercion**: Intelligent preprocessing of expressions to handle mixed int/float arithmetic
- Expressions with float literals automatically convert integer literals to floats
- Context variables containing floats trigger integer-to-float promotion for compatibility
- Preserves array indexing with integers (e.g., `list[2]` remains as integer)
- **Enhanced Error Handling**: Added panic handling with `std::panic::catch_unwind` for parser errors
- Invalid expressions now return proper ValueError instead of crashing the Python process
- Graceful handling of upstream parser panics from cel-interpreter

### Fixed
- **Mixed-type arithmetic compatibility**: Expressions like `3.14 * 2`, `2 + 3.14`, `value * 2` (where value is float) now work as expected
- **Parser panic handling**: Implemented `std::panic::catch_unwind` to gracefully handle upstream parser panics
- Users get proper error messages instead of application crashes
- Fixed deprecation warnings by updating to compatible PyO3 APIs

### Known Issues

- **Bytes Concatenation**: cel-interpreter 0.10.0 does not implement bytes concatenation with `+` operator
- **CEL specification requires**: `b'hello' + b'world'` should work
- **Current behavior**: Returns "Unsupported binary operator 'add'" error
- **Workaround**: Use `bytes(string(part1) + string(part2))` for concatenation
- **Status**: This is a missing feature in the cel-interpreter crate, not a design limitation

### Dependencies Updated
- cel-interpreter: 0.9.0 → 0.10.0 (major version update with breaking changes)
- log: 0.4.22 → 0.4.27
- chrono: 0.4.38 → 0.4.41
- pyo3: 0.22.6 → 0.25.0 (major API upgrade with IntoPyObject migration)
- pyo3-log: 0.11.0 → 0.12.1 (compatible with pyo3 0.25.0)

### Notes
- **PyO3 0.25.0 Migration**: Successfully migrated from deprecated `IntoPy` trait to new `IntoPyObject` API
- **API Improvements**: New conversion system provides better error handling and type safety
- **Build Status**: All 120 tests pass with current dependency versions

12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cel"
version = "0.3.1"
version = "0.4.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand All @@ -9,8 +9,8 @@ name = "cel"
crate-type = ["cdylib"]

[dependencies]
pyo3 = { version = "0.22.6", features = ["chrono", "gil-refs", "py-clone"]}
cel-interpreter = { version = "0.9.0", features = ["chrono", "json", "regex"] }
log = "0.4.22"
pyo3-log = "0.11.0"
chrono = { version = "0.4.38", features = ["serde"] }
pyo3 = { version = "0.25.0", features = ["chrono", "py-clone"]}
cel-interpreter = { version = "0.10.0", features = ["chrono", "json", "regex"] }
log = "0.4.27"
pyo3-log = "0.12.1"
chrono = { version = "0.4.41", features = ["serde"] }
Loading
Loading