Add upstream release watcher (workload-identity auth)#7
Conversation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Swap static ANTHROPIC_API_KEY for OIDC/WIF: add id-token: write and the anthropic_federation_* inputs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
WalkthroughAdds feature-gated Polars DataFrame prediction support, refactors CatBoost platform build handling, and introduces a scheduled workflow that detects upstream releases and creates automated update pull requests. ChangesPolars integration
Platform-specific build handling
Upstream release automation
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant GitHubActions
participant GitHubAPI
participant UpstreamCatBoost
participant ClaudeAction
participant PullRequest
GitHubActions->>GitHubAPI: Fetch latest CatBoost release
GitHubActions->>GitHubActions: Compare pinned and latest versions
GitHubActions->>GitHubAPI: Check for an existing update branch
GitHubActions->>UpstreamCatBoost: Download C API headers
GitHubActions->>GitHubActions: Generate diff and PR body
GitHubActions->>ClaudeAction: Edit wrapper and version references
ClaudeAction->>GitHubActions: Write updated PR body
GitHubActions->>PullRequest: Create labeled update pull request
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
build.rs (1)
178-184: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winWindows aarch64 path skips
.libdownload, will fail at link step.The
("windows", "x86_64")arm (lines 137–177) downloads bothcatboostmodel.dllandcatboostmodel.lib, then returns early. The("windows", "aarch64")arm only returns a.dllURL — the code at lines 254–265 downloads just that file. At line 448,cargo:rustc-link-lib=dylib=catboostmodelmakes the linker look forcatboostmodel.lib, which won't exist, causing a link failure on Windows aarch64.Mirror the x86_64 logic: download both
.dlland.libinside theaarch64arm andreturn Ok(())early.🔧 Proposed fix: download both .dll and .lib for Windows aarch64
("windows", "aarch64") => { - "catboostmodel.dll".to_string(), - format!( - "https://github.com/catboost/catboost/releases/download/v{}/catboostmodel-windows-aarch64-{}.dll", - version, version - ), - ), + let dll_url = format!( + "https://github.com/catboost/catboost/releases/download/v{}/catboostmodel-windows-aarch64-{}.dll", + version, version + ); + println!("cargo:warning=Downloading Windows DLL from: {}", dll_url); + let dll_response = ureq::get(&dll_url).call()?; + if !(200..300).contains(&dll_response.status()) { + return Err( + format!("Failed to download DLL: HTTP {}", dll_response.status()).into(), + ); + } + let dll_path = lib_dir.join("catboostmodel.dll"); + let mut dll_file = fs::File::create(&dll_path)?; + io::copy(&mut dll_response.into_reader(), &mut dll_file)?; + + let lib_url = format!( + "https://github.com/catboost/catboost/releases/download/v{}/catboostmodel-windows-aarch64-{}.lib", + version, version + ); + println!("cargo:warning=Downloading Windows LIB from: {}", lib_url); + let lib_response = ureq::get(&lib_url).call()?; + if !(200..300).contains(&lib_response.status()) { + return Err( + format!("Failed to download LIB: HTTP {}", lib_response.status()).into(), + ); + } + let lib_path = lib_dir.join("catboostmodel.lib"); + let mut lib_file = fs::File::create(&lib_path)?; + io::copy(&mut lib_response.into_reader(), &mut lib_file)?; + + println!( + "cargo:warning=Downloaded CatBoost library to: {}", + dll_path.display() + ); + return Ok(()); + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@build.rs` around lines 178 - 184, Update the Windows aarch64 branch in the build target-selection logic to mirror the Windows x86_64 handling: download both catboostmodel.dll and catboostmodel.lib, then return Ok(()) before the shared download path. Preserve the existing aarch64 DLL URL and use the corresponding library URL and filenames expected by the linker.
🧹 Nitpick comments (2)
src/polars_ext.rs (1)
234-309: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
extract_f32_valueis dead code — never called.
dataframe_to_float_features(lines 124–161) usesseries.cast(&DataType::Float32)directly instead of this function. The 75-line function has no callers in this file. Either remove it or refactordataframe_to_float_featuresto use it if per-type control is desired.♻️ Remove unused function
-/// Extract an f32 value from a Series at the given index -fn extract_f32_value(series: &Series, idx: usize) -> CatBoostResult<f32> { - use DataType::*; - - match series.dtype() { - Float32 => { - let ca = series.f32().map_err(|e| CatBoostError { - description: format!("Failed to cast to f32: {}", e), - })?; - Ok(get_checked_value!(ca, idx)) - } - Float64 => { - let ca = series.f64().map_err(|e| CatBoostError { - description: format!("Failed to cast to f64: {}", e), - })?; - Ok(get_checked_value!(ca, idx) as f32) - } - Int8 => { - let ca = series.i8().map_err(|e| CatBoostError { - description: format!("Failed to cast to i8: {}", e), - })?; - Ok(get_checked_value!(ca, idx) as f32) - } - Int16 => { - let ca = series.i16().map_err(|e| CatBoostError { - description: format!("Failed to cast to i16: {}", e), - })?; - Ok(get_checked_value!(ca, idx) as f32) - } - Int32 => { - let ca = series.i32().map_err(|e| CatBoostError { - description: format!("Failed to cast to i32: {}", e), - })?; - Ok(get_checked_value!(ca, idx) as f32) - } - Int64 => { - let ca = series.i64().map_err(|e| CatBoostError { - description: format!("Failed to cast to i64: {}", e), - })?; - Ok(get_checked_value!(ca, idx) as f32) - } - UInt8 => { - let ca = series.u8().map_err(|e| CatBoostError { - description: format!("Failed to cast to u8: {}", e), - })?; - Ok(get_checked_value!(ca, idx) as f32) - } - UInt16 => { - let ca = series.u16().map_err(|e| CatBoostError { - description: format!("Failed to cast to u16: {}", e), - })?; - Ok(get_checked_value!(ca, idx) as f32) - } - UInt32 => { - let ca = series.u32().map_err(|e| CatBoostError { - description: format!("Failed to cast to u32: {}", e), - })?; - Ok(get_checked_value!(ca, idx) as f32) - } - UInt64 => { - let ca = series.u64().map_err(|e| CatBoostError { - description: format!("Failed to cast to u64: {}", e), - })?; - Ok(get_checked_value!(ca, idx) as f32) - } - Boolean => { - let ca = series.bool().map_err(|e| CatBoostError { - description: format!("Failed to cast to bool: {}", e), - })?; - let val = get_checked_value!(ca, idx); - Ok(if val { 1.0 } else { 0.0 }) - } - dt => Err(CatBoostError { - description: format!("Unsupported data type for float conversion: {}", dt), - }), - } -}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/polars_ext.rs` around lines 234 - 309, Remove the unused extract_f32_value function and its associated conversion logic, since dataframe_to_float_features performs Float32 casting directly and has no callers for this helper..github/workflows/upstream-release.yml (1)
95-95: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winPin actions to a commit SHA for supply-chain security.
Both
anthropics/claude-code-action@v1andpeter-evans/create-pull-request@v6are pinned to mutable version tags. A compromised tag would execute arbitrary code in a workflow withid-token: write,contents: write, andpull-requests: writepermissions. Pin to a specific commit SHA and optionally add a comment with the version for readability.🔒️ Example pinning
- uses: anthropics/claude-code-action@v1 + uses: anthropics/claude-code-action@<full-commit-sha> # v1- uses: peter-evans/create-pull-request@v6 + uses: peter-evans/create-pull-request@<full-commit-sha> # v6Also applies to: 165-165
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/upstream-release.yml at line 95, Update the action references in the workflow steps using anthropics/claude-code-action and peter-evans/create-pull-request to immutable commit SHA pins instead of mutable version tags, optionally retaining the human-readable version in comments.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/upstream-release.yml:
- Line 77: Update the shell options in the affected run block of the upstream
release workflow from set -uo pipefail to set -euo pipefail. Preserve the
existing || true guards for expected curl and diff failures while ensuring
unexpected command failures stop the step.
- Around line 40-44: Validate LATEST in the upstream release-version step before
writing the GitHub output, allowing only the expected CatBoost version format
after removing the leading v; reject empty or any value containing
shell/template metacharacters with an error and nonzero exit. Keep the existing
current/latest outputs unchanged for valid versions so downstream uses of
steps.versions.outputs.latest remain safe.
In `@src/polars_ext.rs`:
- Around line 312-387: Update extract_string_value to handle Float32 and Float64
series by retrieving values through the corresponding Polars accessors and
converting them to strings, consistent with the existing integer arms. Preserve
the existing String, integer, Boolean, and unsupported-type behavior.
---
Outside diff comments:
In `@build.rs`:
- Around line 178-184: Update the Windows aarch64 branch in the build
target-selection logic to mirror the Windows x86_64 handling: download both
catboostmodel.dll and catboostmodel.lib, then return Ok(()) before the shared
download path. Preserve the existing aarch64 DLL URL and use the corresponding
library URL and filenames expected by the linker.
---
Nitpick comments:
In @.github/workflows/upstream-release.yml:
- Line 95: Update the action references in the workflow steps using
anthropics/claude-code-action and peter-evans/create-pull-request to immutable
commit SHA pins instead of mutable version tags, optionally retaining the
human-readable version in comments.
In `@src/polars_ext.rs`:
- Around line 234-309: Remove the unused extract_f32_value function and its
associated conversion logic, since dataframe_to_float_features performs Float32
casting directly and has no callers for this helper.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 2d35438e-7d46-425e-9483-233398df7f00
📒 Files selected for processing (5)
.github/workflows/upstream-release.ymlCargo.tomlbuild.rssrc/lib.rssrc/polars_ext.rs
| LATEST=$(gh api "repos/catboost/catboost/releases/latest" --jq '.tag_name' | sed 's/^v//') | ||
| [ -n "$LATEST" ] || { echo "::error::Could not fetch latest release"; exit 1; } | ||
|
|
||
| echo "current=$CURRENT" >> "$GITHUB_OUTPUT" | ||
| echo "latest=$LATEST" >> "$GITHUB_OUTPUT" |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Validate version format to prevent shell template injection.
LATEST is derived from the upstream catboost/catboost release tag name via gh api ... --jq '.tag_name' | sed 's/^v//'. The sed only strips a leading v — it does not sanitize other characters. This value is then injected directly into a shell script at line 63 (BRANCH="chore/catboost-${{ steps.versions.outputs.latest }}"), where an attacker-controlled tag containing shell metacharacters (e.g., $(...) or backticks) would execute arbitrary commands with contents: write and pull-requests: write permissions.
Add a strict version-format validation before setting the output:
🔒️ Proposed fix: validate version format
LATEST=$(gh api "repos/catboost/catboost/releases/latest" --jq '.tag_name' | sed 's/^v//')
[ -n "$LATEST" ] || { echo "::error::Could not fetch latest release"; exit 1; }
+
+ # Reject anything that isn't a clean semver — prevents template injection downstream
+ echo "$LATEST" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$' || {
+ echo "::error::Latest upstream tag is not a clean semver: '$LATEST'"
+ exit 1
+ }
+ echo "$CURRENT" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$' || {
+ echo "::error::Pinned version is not a clean semver: '$CURRENT'"
+ exit 1
+ }This protects all downstream uses of steps.versions.outputs.latest (lines 63, 115, 120, 138, 147, 168–170).
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| LATEST=$(gh api "repos/catboost/catboost/releases/latest" --jq '.tag_name' | sed 's/^v//') | |
| [ -n "$LATEST" ] || { echo "::error::Could not fetch latest release"; exit 1; } | |
| echo "current=$CURRENT" >> "$GITHUB_OUTPUT" | |
| echo "latest=$LATEST" >> "$GITHUB_OUTPUT" | |
| LATEST=$(gh api "repos/catboost/catboost/releases/latest" --jq '.tag_name' | sed 's/^v//') | |
| [ -n "$LATEST" ] || { echo "::error::Could not fetch latest release"; exit 1; } | |
| # Reject anything that isn't a clean semver — prevents template injection downstream | |
| echo "$LATEST" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$' || { | |
| echo "::error::Latest upstream tag is not a clean semver: '$LATEST'" | |
| exit 1 | |
| } | |
| echo "$CURRENT" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$' || { | |
| echo "::error::Pinned version is not a clean semver: '$CURRENT'" | |
| exit 1 | |
| } | |
| echo "current=$CURRENT" >> "$GITHUB_OUTPUT" | |
| echo "latest=$LATEST" >> "$GITHUB_OUTPUT" |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/upstream-release.yml around lines 40 - 44, Validate LATEST
in the upstream release-version step before writing the GitHub output, allowing
only the expected CatBoost version format after removing the leading v; reject
empty or any value containing shell/template metacharacters with an error and
nonzero exit. Keep the existing current/latest outputs unchanged for valid
versions so downstream uses of steps.versions.outputs.latest remain safe.
Source: Linters/SAST tools
| CURRENT: ${{ steps.versions.outputs.current }} | ||
| LATEST: ${{ steps.versions.outputs.latest }} | ||
| run: | | ||
| set -uo pipefail |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
Add set -e for consistency with other steps.
This step uses set -uo pipefail while all other run blocks use set -euo pipefail. Without -e, unexpected failures (e.g., printf at line 88) are silently ignored, potentially producing an incomplete diff or PR body. The existing || true guards on curl and diff already handle expected non-zero exits, so adding -e is safe.
✏️ Proposed fix
- set -uo pipefail
+ set -euo pipefail📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| set -uo pipefail | |
| set -euo pipefail |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/upstream-release.yml at line 77, Update the shell options
in the affected run block of the upstream release workflow from set -uo pipefail
to set -euo pipefail. Preserve the existing || true guards for expected curl and
diff failures while ensuring unexpected command failures stop the step.
| fn extract_string_value(series: &Series, idx: usize) -> CatBoostResult<String> { | ||
| use DataType::*; | ||
|
|
||
| match series.dtype() { | ||
| String => { | ||
| let ca = series.str().map_err(|e| CatBoostError { | ||
| description: format!("Failed to cast to String: {}", e), | ||
| })?; | ||
| Ok(get_checked_value!(ca, idx).to_string()) | ||
| } | ||
| // Convert numeric types to strings for categorical features | ||
| // Handle each integer type directly to avoid precision loss | ||
| Int8 => { | ||
| let ca = series.i8().map_err(|e| CatBoostError { | ||
| description: format!("Failed to cast to i8: {}", e), | ||
| })?; | ||
| Ok(get_checked_value!(ca, idx).to_string()) | ||
| } | ||
| Int16 => { | ||
| let ca = series.i16().map_err(|e| CatBoostError { | ||
| description: format!("Failed to cast to i16: {}", e), | ||
| })?; | ||
| Ok(get_checked_value!(ca, idx).to_string()) | ||
| } | ||
| Int32 => { | ||
| let ca = series.i32().map_err(|e| CatBoostError { | ||
| description: format!("Failed to cast to i32: {}", e), | ||
| })?; | ||
| Ok(get_checked_value!(ca, idx).to_string()) | ||
| } | ||
| Int64 => { | ||
| let ca = series.i64().map_err(|e| CatBoostError { | ||
| description: format!("Failed to cast to i64: {}", e), | ||
| })?; | ||
| Ok(get_checked_value!(ca, idx).to_string()) | ||
| } | ||
| UInt8 => { | ||
| let ca = series.u8().map_err(|e| CatBoostError { | ||
| description: format!("Failed to cast to u8: {}", e), | ||
| })?; | ||
| Ok(get_checked_value!(ca, idx).to_string()) | ||
| } | ||
| UInt16 => { | ||
| let ca = series.u16().map_err(|e| CatBoostError { | ||
| description: format!("Failed to cast to u16: {}", e), | ||
| })?; | ||
| Ok(get_checked_value!(ca, idx).to_string()) | ||
| } | ||
| UInt32 => { | ||
| let ca = series.u32().map_err(|e| CatBoostError { | ||
| description: format!("Failed to cast to u32: {}", e), | ||
| })?; | ||
| Ok(get_checked_value!(ca, idx).to_string()) | ||
| } | ||
| UInt64 => { | ||
| let ca = series.u64().map_err(|e| CatBoostError { | ||
| description: format!("Failed to cast to u64: {}", e), | ||
| })?; | ||
| Ok(get_checked_value!(ca, idx).to_string()) | ||
| } | ||
| Boolean => { | ||
| let ca = series.bool().map_err(|e| CatBoostError { | ||
| description: format!("Failed to cast to bool: {}", e), | ||
| })?; | ||
| let val = get_checked_value!(ca, idx); | ||
| Ok(if val { | ||
| "true".to_string() | ||
| } else { | ||
| "false".to_string() | ||
| }) | ||
| } | ||
| dt => Err(CatBoostError { | ||
| description: format!("Unsupported data type for categorical conversion: {}", dt), | ||
| }), | ||
| } | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
extract_string_value rejects Float32/Float64 columns for categorical features.
The function handles String, all integer types, and Boolean, but returns "Unsupported data type for categorical conversion" for Float32/Float64. A user passing a float column as a categorical feature gets a confusing error. Consider adding Float32/Float64 arms that convert to string.
🛡️ Add float handling
Boolean => {
let ca = series.bool().map_err(|e| CatBoostError {
description: format!("Failed to cast to bool: {}", e),
})?;
let val = get_checked_value!(ca, idx);
Ok(if val {
"true".to_string()
} else {
"false".to_string()
})
}
+ Float32 => {
+ let ca = series.f32().map_err(|e| CatBoostError {
+ description: format!("Failed to cast to f32: {}", e),
+ })?;
+ Ok(get_checked_value!(ca, idx).to_string())
+ }
+ Float64 => {
+ let ca = series.f64().map_err(|e| CatBoostError {
+ description: format!("Failed to cast to f64: {}", e),
+ })?;
+ Ok(get_checked_value!(ca, idx).to_string())
+ }
dt => Err(CatBoostError {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| fn extract_string_value(series: &Series, idx: usize) -> CatBoostResult<String> { | |
| use DataType::*; | |
| match series.dtype() { | |
| String => { | |
| let ca = series.str().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to String: {}", e), | |
| })?; | |
| Ok(get_checked_value!(ca, idx).to_string()) | |
| } | |
| // Convert numeric types to strings for categorical features | |
| // Handle each integer type directly to avoid precision loss | |
| Int8 => { | |
| let ca = series.i8().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to i8: {}", e), | |
| })?; | |
| Ok(get_checked_value!(ca, idx).to_string()) | |
| } | |
| Int16 => { | |
| let ca = series.i16().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to i16: {}", e), | |
| })?; | |
| Ok(get_checked_value!(ca, idx).to_string()) | |
| } | |
| Int32 => { | |
| let ca = series.i32().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to i32: {}", e), | |
| })?; | |
| Ok(get_checked_value!(ca, idx).to_string()) | |
| } | |
| Int64 => { | |
| let ca = series.i64().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to i64: {}", e), | |
| })?; | |
| Ok(get_checked_value!(ca, idx).to_string()) | |
| } | |
| UInt8 => { | |
| let ca = series.u8().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to u8: {}", e), | |
| })?; | |
| Ok(get_checked_value!(ca, idx).to_string()) | |
| } | |
| UInt16 => { | |
| let ca = series.u16().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to u16: {}", e), | |
| })?; | |
| Ok(get_checked_value!(ca, idx).to_string()) | |
| } | |
| UInt32 => { | |
| let ca = series.u32().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to u32: {}", e), | |
| })?; | |
| Ok(get_checked_value!(ca, idx).to_string()) | |
| } | |
| UInt64 => { | |
| let ca = series.u64().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to u64: {}", e), | |
| })?; | |
| Ok(get_checked_value!(ca, idx).to_string()) | |
| } | |
| Boolean => { | |
| let ca = series.bool().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to bool: {}", e), | |
| })?; | |
| let val = get_checked_value!(ca, idx); | |
| Ok(if val { | |
| "true".to_string() | |
| } else { | |
| "false".to_string() | |
| }) | |
| } | |
| dt => Err(CatBoostError { | |
| description: format!("Unsupported data type for categorical conversion: {}", dt), | |
| }), | |
| } | |
| } | |
| fn extract_string_value(series: &Series, idx: usize) -> CatBoostResult<String> { | |
| use DataType::*; | |
| match series.dtype() { | |
| String => { | |
| let ca = series.str().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to String: {}", e), | |
| })?; | |
| Ok(get_checked_value!(ca, idx).to_string()) | |
| } | |
| // Convert numeric types to strings for categorical features | |
| // Handle each integer type directly to avoid precision loss | |
| Int8 => { | |
| let ca = series.i8().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to i8: {}", e), | |
| })?; | |
| Ok(get_checked_value!(ca, idx).to_string()) | |
| } | |
| Int16 => { | |
| let ca = series.i16().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to i16: {}", e), | |
| })?; | |
| Ok(get_checked_value!(ca, idx).to_string()) | |
| } | |
| Int32 => { | |
| let ca = series.i32().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to i32: {}", e), | |
| })?; | |
| Ok(get_checked_value!(ca, idx).to_string()) | |
| } | |
| Int64 => { | |
| let ca = series.i64().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to i64: {}", e), | |
| })?; | |
| Ok(get_checked_value!(ca, idx).to_string()) | |
| } | |
| UInt8 => { | |
| let ca = series.u8().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to u8: {}", e), | |
| })?; | |
| Ok(get_checked_value!(ca, idx).to_string()) | |
| } | |
| UInt16 => { | |
| let ca = series.u16().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to u16: {}", e), | |
| })?; | |
| Ok(get_checked_value!(ca, idx).to_string()) | |
| } | |
| UInt32 => { | |
| let ca = series.u32().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to u32: {}", e), | |
| })?; | |
| Ok(get_checked_value!(ca, idx).to_string()) | |
| } | |
| UInt64 => { | |
| let ca = series.u64().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to u64: {}", e), | |
| })?; | |
| Ok(get_checked_value!(ca, idx).to_string()) | |
| } | |
| Boolean => { | |
| let ca = series.bool().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to bool: {}", e), | |
| })?; | |
| let val = get_checked_value!(ca, idx); | |
| Ok(if val { | |
| "true".to_string() | |
| } else { | |
| "false".to_string() | |
| }) | |
| } | |
| Float32 => { | |
| let ca = series.f32().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to f32: {}", e), | |
| })?; | |
| Ok(get_checked_value!(ca, idx).to_string()) | |
| } | |
| Float64 => { | |
| let ca = series.f64().map_err(|e| CatBoostError { | |
| description: format!("Failed to cast to f64: {}", e), | |
| })?; | |
| Ok(get_checked_value!(ca, idx).to_string()) | |
| } | |
| dt => Err(CatBoostError { | |
| description: format!("Unsupported data type for categorical conversion: {}", dt), | |
| }), | |
| } | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/polars_ext.rs` around lines 312 - 387, Update extract_string_value to
handle Float32 and Float64 series by retrieving values through the corresponding
Polars accessors and converting them to strings, consistent with the existing
integer arms. Preserve the existing String, integer, Boolean, and
unsupported-type behavior.
Adds a weekly (and manual) watcher that opens a PR when the upstream library
publishes a newer release than the one pinned in
build.rs. Claude reviews theupstream C API header diff and edits the crate;
peter-evans/create-pull-requestopens the PR. The only remote write is the PR itself.
Auth: Anthropic workload identity federation (OIDC) — no stored API key.
Before this can run, add repo secrets:
ANTHROPIC_FEDERATION_RULE_ID,ANTHROPIC_ORGANIZATION_ID,ANTHROPIC_SERVICE_ACCOUNT_ID(+
ANTHROPIC_WORKSPACE_IDif the federation rule spans multiple workspaces).Note: the federation rule subject should match this repo\x27s default branch once merged.
🤖 Generated with Claude Code
Summary by CodeRabbit
polarscrate feature for opt-in use.