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
16 changes: 16 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
version: 2

updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: daily
cooldown:
default-days: 7

- package-ecosystem: cargo
directory: /
schedule:
interval: daily
cooldown:
default-days: 7
58 changes: 37 additions & 21 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@ on:
- "**"
pull_request: {}

permissions: {}

jobs:
test:
name: test ${{ matrix.python-version }} pandas ${{ matrix.pandas-version }}
permissions:
contents: read
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -43,29 +47,31 @@ jobs:
PYTHON: ${{ matrix.python-version }}

steps:
- uses: actions/checkout@v6
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false

- name: install rust stable
uses: dtolnay/rust-toolchain@master
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
with:
toolchain: stable

- id: cache-rust
name: cache rust
uses: Swatinem/rust-cache@v2
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "CI.yml" -o -name "ci.yml" | head -20

Repository: dimastbk/python-calamine

Length of output: 95


🏁 Script executed:

cat -n .github/workflows/CI.yml | sed -n '50,130p'

Repository: dimastbk/python-calamine

Length of output: 2995


🏁 Script executed:

cat -n .github/workflows/CI.yml | head -50

Repository: dimastbk/python-calamine

Length of output: 1656


🏁 Script executed:

cat -n .github/workflows/CI.yml | sed -n '1,100p' | grep -A 20 "^.*on:"

Repository: dimastbk/python-calamine

Length of output: 2752


🌐 Web query:

Swatinem/rust-cache v2.9.1 default behavior pull_request save behavior

💡 Result:

In Swatinem/rust-cache v2.9.1, the default behavior for saving the cache is to always save it, regardless of whether the workflow run is triggered by a pull request or a push [1][2]. The action provides an input option called save-if that controls this behavior [1]. By default, save-if is set to "true" [1][3]. When this default is active, the action will restore the cache (if available) and then save the cache at the end of the job run [1][4]. If you wish to change this behavior—for example, to prevent pull requests from overwriting the main branch's cache or to only save cache when running on specific branches—you can explicitly configure the save-if input [1][3]. A common use case is to restrict saves to the default branch using a GitHub Actions expression [1]: save-if: ${{ github.ref == 'refs/heads/main' }} It is important to note that GitHub Actions has its own native caching scope restrictions: caches created in a pull request are generally only accessible to that specific pull request or the base branch from which it originated, meaning they cannot "pollute" or overwrite the primary cache of other branches unless specifically managed [5]. If you notice that cache is not being "found" in a PR, it is often due to these native GitHub cache scoping rules rather than the save-if configuration [5].

Citations:


🌐 Web query:

actions/cache v5.0.5 GitHub Actions pull_request write behavior default

💡 Result:

In GitHub Actions, the actions/cache@v5.0.5 action does not rely on the permissions block defined in your workflow file to determine its ability to write to the GitHub Actions cache [1][2]. Instead, cache operations are managed by GitHub's internal runner-scoped tokens, which automatically grant write access for workflows running on pull_request events within the repository [3][2]. Key behaviors regarding pull_request and cache write access include: 1. Automatic Write Capability: By default, jobs triggered by pull_request events have permission to create and write to caches within the scope of that specific pull request [3][4]. This allows workflows to "warm" a cache during a PR run. 2. Scope Isolation: Caches created during a pull_request run are restricted to that specific PR (specifically, the merge ref, refs/pull/.../merge) [3][4]. They cannot be restored by other pull requests or by the base branch, preventing unauthorized cache poisoning across different branches [3][4]. 3. Security Considerations: Because cache write operations bypass standard permissions: contents: read limitations, they can pose a security risk if a workflow runs in an untrusted context (e.g., pull_request_target or workflows that check out external PR head code) [1][2]. A malicious pull request could potentially "poison" the cache, which might then be restored by a subsequent trusted run on the main branch [1][2]. To mitigate these security risks, it is recommended to restrict cache writes for untrusted PR builds [1][2]. You can achieve this by using the actions/cache/restore@v5 sub-action instead of the full actions/cache@v5 action, or by adding a conditional check to ensure that the cache save step is skipped for pull_request events [1][2]: if: github.event_name!= 'pull_request' && github.event_name!= 'pull_request_target' uses: actions/cache@v5 with:...

Citations:


Restrict cache saves to trusted push events.

These cache steps currently enable save behavior on all pull_request runs. While GitHub's cache scoping prevents PR caches from overwriting the main branch cache, explicitly gating cache saves to trusted events (push) is a security best practice. Gate cache save using save-if conditionals, and allow restore for all events.

Mitigation pattern
-      - id: cache-rust
-        name: cache rust
-        uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
+      - id: cache-rust
+        name: cache rust
+        uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
         with:
           key: v3
+          save-if: ${{ github.event_name == 'push' }}

For actions/cache, use the restore-only action on PRs and split to separate save step with event gating on trusted pushes.

Applies to lines: 61, 74, 115, 121

🧰 Tools
🪛 zizmor (1.25.2)

[error] 61-61: runtime artifacts potentially vulnerable to a cache poisoning attack (cache-poisoning): enables caching by default

(cache-poisoning)

🤖 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/CI.yml at line 61, The rust-cache action at line 61 (and
also at lines 74, 115, and 121) currently allows cache saves on all pull_request
runs, which is a security risk. Add a `save-if` conditional to each of these
cache steps that restricts cache saves to trusted push events only. Use `if:
github.event_name == 'push'` as the save condition while keeping the restore
functionality available for all events. This follows the pattern of using the
restore-only behavior on PRs and splitting to a separate cache step with
explicit event gating for saves.

Source: Linters/SAST tools

with:
key: v3

- name: set up python
uses: actions/setup-python@v6
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
if: "${{ !matrix.disable-gil }}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n .github/workflows/CI.yml | head -80

Repository: dimastbk/python-calamine

Length of output: 2789


🏁 Script executed:

# Check if disable-gil appears anywhere else in the workflow
rg "disable-gil" .github/workflows/CI.yml

# Also check the full context around line 67 to see if there's more matrix definition
cat -n .github/workflows/CI.yml | sed -n '23,42p'

Repository: dimastbk/python-calamine

Length of output: 865


🏁 Script executed:

# Check all jobs in the workflow to see if any other job defines disable-gil
rg -A 20 "jobs:" .github/workflows/CI.yml | head -100

# Also check the entire workflow for all matrix definitions
rg "matrix:" .github/workflows/CI.yml -A 15

Repository: dimastbk/python-calamine

Length of output: 2130


🏁 Script executed:

# Get the entire CI.yml file to see all jobs and confirm disable-gil is not defined anywhere
wc -l .github/workflows/CI.yml

# Let's see the full file structure to be thorough
cat -n .github/workflows/CI.yml | tail -100

Repository: dimastbk/python-calamine

Length of output: 4169


Remove the undefined matrix key guard at Line 67.

matrix.disable-gil is not part of the declared matrix object, so this condition is invalid and will fail workflow validation. Remove the if statement since it references a non-existent matrix variable.

Proposed fix
      - name: set up python
        uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
-       if: "${{ !matrix.disable-gil }}"
        with:
          python-version: ${{ matrix.python-version }}
          allow-prereleases: true
📝 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.

Suggested change
if: "${{ !matrix.disable-gil }}"
- name: set up python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
🧰 Tools
🪛 actionlint (1.7.12)

[error] 67-67: property "disable-gil" is not defined in object type {pandas-version: string; python-version: string}

(expression)

🤖 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/CI.yml at line 67, Remove the `if: "${{
!matrix.disable-gil }}"` condition line from the workflow step. The
`disable-gil` key is not defined in the matrix object declaration, making this
condition invalid and causing workflow validation to fail. Simply delete this
entire line to resolve the issue.

Source: Linters/SAST tools

with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true

- id: cache-py
name: cache python
uses: actions/cache@v5
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ env.pythonLocation }}
key: >
Expand All @@ -91,24 +97,28 @@ jobs:
- run: pytest

lint:
permissions:
contents: read
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v6
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false

- name: install rust stable
uses: dtolnay/rust-toolchain@stable
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
with:
components: rustfmt, clippy

- name: cache rust
uses: Swatinem/rust-cache@v2
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1

- uses: actions/setup-python@v6
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.14"

- uses: actions/cache@v5
- uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
id: cache-py
name: cache python
with:
Expand All @@ -134,12 +144,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@release/v1
uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2
with:
jobs: ${{ toJSON(needs) }}

build:
name: build on ${{ matrix.os }} (${{ matrix.target }} - ${{ matrix.interpreter || 'all' }}${{ matrix.os == 'linux' && format(' - {0}', matrix.manylinux == 'auto' && 'manylinux' || matrix.manylinux) || '' }})
permissions:
contents: read
if: success()
strategy:
fail-fast: false
Expand Down Expand Up @@ -206,39 +218,43 @@ jobs:

runs-on: ${{ matrix.runs-on || format('{0}-latest', (matrix.os == 'linux' && 'ubuntu') || matrix.os) }}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false

- name: set up python
uses: actions/setup-python@v6
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.14"

- name: install rust stable
uses: dtolnay/rust-toolchain@stable
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable

- run: pip install -U twine

- name: build sdist
if: ${{ matrix.os == 'linux' && matrix.target == 'x86_64' && matrix.manylinux == 'auto' }}
uses: PyO3/maturin-action@v1
uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0
with:
command: sdist
args: --out dist
rust-toolchain: stable
maturin-version: 1.13.3 # Free-threaded Python interpreter is only supported on 3.14 and later.

- name: build wheels
uses: PyO3/maturin-action@v1
uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0
with:
target: ${{ matrix.target }}
manylinux: ${{ matrix.manylinux || 'auto' }}
args: --release --out dist --interpreter ${{ matrix.interpreter || '3.10 3.11 3.12 3.13 3.13t 3.14 3.14t pypy3.11' }}
rust-toolchain: stable
maturin-version: 1.13.3 # Free-threaded Python interpreter is only supported on 3.14 and later.

- run: ${{ (matrix.os == 'windows' && 'dir') || 'ls -lh' }} dist/

- run: twine check --strict dist/*

- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: wheels-${{ matrix.os }}-${{ matrix.target }}-${{ matrix.manylinux || 'auto' }}
path: dist
Expand All @@ -258,14 +274,14 @@ jobs:

steps:
- name: Download All Artifacts
uses: actions/download-artifact@v8
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: dist
pattern: wheels-*
merge-multiple: true

- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1.14

gh-release:
needs: [build, check]
Expand All @@ -278,14 +294,14 @@ jobs:

steps:
- name: Download All Artifacts
uses: actions/download-artifact@v8
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: dist
pattern: wheels-*
merge-multiple: true

- name: Upload to GitHub
uses: softprops/action-gh-release@v3.0.0
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
with:
generate_release_notes: true
files: |
Expand Down
6 changes: 0 additions & 6 deletions renovate.json

This file was deleted.