Skip to content
Open
Show file tree
Hide file tree
Changes from 25 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
58 changes: 58 additions & 0 deletions .github/workflows/test_dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Development Tests

on:
schedule:
- cron: 0 0 * * *
workflow_dispatch:
push:
paths:
- '.github/**'
- 'test/CoolPropDevLoader/**'

concurrency:
# Skip intermediate builds: all builds except for builds on the `master` branch
# Cancel intermediate builds: only pull request builds
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref != 'refs/heads/master' || github.run_number }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}

jobs:
test-coolprop-dev:
timeout-minutes: 30
strategy:
matrix:
julia_version:
- '1.12'
os:
- ubuntu-latest
julia_arch:
- x64
fail-fast: false
runs-on: ${{ matrix.os }}

steps:
- name: Checkout
uses: actions/checkout@v7

- uses: julia-actions/setup-julia@v3
with:
arch: ${{ matrix.julia_arch }}
version: ${{ matrix.julia_version }}
- uses: julia-actions/cache@v3

- name: add CoolPropDevLoader
shell: julia --color=yes --project=. {0}
run: |
using Pkg
Pkg.develop(path="test/CoolPropDevLoader")

- name: Compiling CoolProp
shell: julia --color=yes --compiled-modules=no --project=test {0}
run: |
using Pkg
Pkg.develop(path="test/CoolPropDevLoader")
using CoolPropDevLoader
CoolPropDevLoader.use_dev_library(CoolPropDevLoader.CompileCoolPropFromSourceforge())
Pkg.add("Test")

- uses: julia-actions/julia-runtest@v1

Comment on lines +1 to +61

@coderabbitai coderabbitai Bot Jul 9, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Add permissions block and set persist-credentials: false on checkout.

The workflow lacks a permissions block, defaulting to the token's full permissions set. Since this workflow only runs tests, it should use minimal permissions. Additionally, actions/checkout persists the GitHub token by default, which is unnecessary here and flagged by zizmor as a credential persistence risk.

🔒 Proposed security hardening
 name: Development Tests
 
 on:
   schedule:
     - cron: 0 0 * * *
   workflow_dispatch:
   push:
     paths:
       - '.github/**'
       - 'test/CoolPropDevLoader/**'
 
+permissions:
+  contents: read
+
 concurrency:
   # Skip intermediate builds: all builds except for builds on the `master` branch
   # Cancel intermediate builds: only pull request builds
   group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref != 'refs/heads/master' || github.run_number }}
   cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
 
 jobs:
   test-coolprop-dev:
     timeout-minutes: 30
     strategy:
       matrix:
         julia_version:
           - '1.12'
         os:
           - ubuntu-latest
         julia_arch:
           - x64
       fail-fast: false
     runs-on: ${{ matrix.os }}
 
     steps:
     - name: Checkout
       uses: actions/checkout@v7
+      with:
+        persist-credentials: false
📝 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
name: Development Tests
on:
schedule:
- cron: 0 0 * * *
workflow_dispatch:
push:
paths:
- '.github/**'
- 'test/CoolPropDevLoader/**'
concurrency:
# Skip intermediate builds: all builds except for builds on the `master` branch
# Cancel intermediate builds: only pull request builds
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref != 'refs/heads/master' || github.run_number }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
jobs:
test-coolprop-dev:
timeout-minutes: 30
strategy:
matrix:
julia_version:
- '1.12'
os:
- ubuntu-latest
julia_arch:
- x64
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v7
- uses: julia-actions/setup-julia@v3
with:
arch: ${{ matrix.julia_arch }}
version: ${{ matrix.julia_version }}
- uses: julia-actions/cache@v3
- name: add CoolPropDevLoader
shell: julia --color=yes --project=. {0}
run: |
using Pkg
Pkg.develop(path="test/CoolPropDevLoader")
- name: Compiling CoolProp
shell: julia --color=yes --compiled-modules=no --project=test {0}
run: |
using Pkg
Pkg.develop(path="test/CoolPropDevLoader")
using CoolPropDevLoader
CoolPropDevLoader.use_dev_library(CoolPropDevLoader.CompileCoolPropFromSourceforge())
Pkg.add("Test")
- uses: julia-actions/julia-runtest@v1
name: Development Tests
on:
schedule:
- cron: 0 0 * * *
workflow_dispatch:
push:
paths:
- '.github/**'
- 'test/CoolPropDevLoader/**'
permissions:
contents: read
concurrency:
# Skip intermediate builds: all builds except for builds on the `master` branch
# Cancel intermediate builds: only pull request builds
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref != 'refs/heads/master' || github.run_number }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
jobs:
test-coolprop-dev:
timeout-minutes: 30
strategy:
matrix:
julia_version:
- '1.12'
os:
- ubuntu-latest
julia_arch:
- x64
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v7
with:
persist-credentials: false
- uses: julia-actions/setup-julia@v3
with:
arch: ${{ matrix.julia_arch }}
version: ${{ matrix.julia_version }}
- uses: julia-actions/cache@v3
- name: add CoolPropDevLoader
shell: julia --color=yes --project=. {0}
run: |
using Pkg
Pkg.develop(path="test/CoolPropDevLoader")
- name: Compiling CoolProp
shell: julia --color=yes --compiled-modules=no --project=test {0}
run: |
using Pkg
Pkg.develop(path="test/CoolPropDevLoader")
using CoolPropDevLoader
CoolPropDevLoader.use_dev_library(CoolPropDevLoader.CompileCoolPropFromSourceforge())
Pkg.add("Test")
- uses: julia-actions/julia-runtest@v1
🧰 Tools
🪛 zizmor (1.26.1)

[warning] 33-34: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[warning] 19-58: overly broad permissions (excessive-permissions): default permissions used due to no permissions: block

(excessive-permissions)

🤖 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/test_dev.yml around lines 1 - 58, The workflow needs
tighter GitHub Actions security settings: add an explicit minimal permissions
block at the workflow level, since it only runs tests, and disable token
persistence in the Checkout step. Update the `test-coolprop-dev` workflow by
setting least-privilege permissions and changing the `actions/checkout` usage so
`persist-credentials` is false. Use the existing `Checkout` step and the
workflow header near `name: Development Tests` to locate the changes.

Source: Linters/SAST tools

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The code compiles CoolProp and creates a directory inside the test folder, only read permissions are not enough

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@longemen3000, good question — but this is a common mix-up between two different types of "permissions."

The permissions: block in a GitHub Actions workflow only controls the scope of the GITHUB_TOKEN used for calls to the GitHub API (e.g., pushing commits, creating releases/comments, writing to packages, etc.). It has no effect on local filesystem operations on the runner's disk.

Since this workflow's build step (compiling CoolProp via CMake, creating a build directory under test/, downloading the SourceForge archive, etc.) only writes to the runner's local disk and never pushes back to the repository or calls the GitHub API to write content, contents: read is sufficient. The job can still freely create directories, compile code, and download files locally — that's unrelated to the token's API scope.

So contents: read won't block the compile step; it just prevents the GITHUB_TOKEN from being used to push/write to the repo via the API, which this workflow doesn't do anyway. Let me know if you're hitting an actual permission-denied error from a specific step, and I can help dig into that separately.


✏️ Learnings added
Learnt from: longemen3000
Repo: CoolProp/CoolProp.jl PR: 52
File: .github/workflows/test_dev.yml:1-58
Timestamp: 2026-07-09T06:28:06.309Z
Learning: In CoolProp.jl's `.github/workflows/*.yml` files, the workflow author (longemen3000) may confuse the GitHub Actions `permissions:` block (which scopes the GITHUB_TOKEN for GitHub API calls) with local filesystem write permissions on the runner. Clarify that `permissions: contents: read` does not restrict local disk operations like compiling code or creating directories in `test/CoolPropDevLoader`, since those don't use the GITHUB_TOKEN.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ version = "0.2.2"
[deps]
CoolProp_jll = "3351c21f-4feb-5f29-afb9-f4fcb0e27549"
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
Preferences = "21216c6a-2e73-6563-6e65-726566657250"
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"

[compat]
CoolProp_jll = "6.6, 7.1"
julia = "1.3"
Unitful="1"
Preferences = "1"
Unitful = "1"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ using Unitful: °C, Pa

HAPropsSI("H", "Tdb", 20°C, "RH", 0.5, "P", 101325Pa)
38622.83892391293 J kg⁻¹
```
```
14 changes: 13 additions & 1 deletion src/CoolProp.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
#__precompile__()
module CoolProp



import Unitful
using CoolProp_jll
import CoolProp_jll

@static if VERSION >= v"1.6"
using Preferences
end

@static if VERSION >= v"1.6"
const libcoolprop = load_preference(CoolProp_jll,"coolprop_library", CoolProp_jll.libcoolprop)
else
const libcoolprop = CoolProp_jll.libcoolprop
end

####################################################################################################################
####################################################################################################################
Expand Down
2 changes: 2 additions & 0 deletions test/CoolProp.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#__precompile__()
module CoolProp

@info "CoolProp library path: $(CoolProp.libcoolprop)"

errcode = Ref{Clong}(0)
const buffer_length = 20000
message_buffer = Array(UInt8, buffer_length)
Expand Down
20 changes: 20 additions & 0 deletions test/CoolPropDevLoader/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name = "CoolPropDevLoader"
uuid = "1abf7821-c65a-4ba0-83a4-5660520f37c7"
version = "1.0.0"

[deps]
Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
Preferences = "21216c6a-2e73-6563-6e65-726566657250"
CoolProp_jll = "3351c21f-4feb-5f29-afb9-f4fcb0e27549"

[compat]
Downloads = "1"
julia = "1.3"
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
Preferences = "1"
CoolProp_jll = "6.6, 7.1"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test"]
110 changes: 110 additions & 0 deletions test/CoolPropDevLoader/src/CoolPropDevLoader.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
module CoolPropDevLoader

using Preferences
using Downloads
using CoolProp_jll

const SOURCEFORGE_URL = "https://sourceforge.net/projects/coolprop/files/CoolProp/nightly/source/CoolProp_sources.zip/download"

#only available in linux
function compile_from_sourceforge()
# 1. Configuration
url = SOURCEFORGE_URL
build_dir = joinpath(@__DIR__, "coolprop_build") # Change as needed
source_zip = joinpath(build_dir, "CoolProp_sources.zip")
extract_dir = build_dir # We'll extract directly into build_dir, then locate source root
lib_name = "libCoolProp.so"

# 2. Create build directory
mkpath(build_dir)
mkpath(extract_dir)

# 3. Download the source zip
@info "Downloading CoolProp source from $url..."
Downloads.download(SOURCEFORGE_URL, source_zip)

# 4. Extract the zip into build_dir
@info "Extracting source..."
run(`unzip -q $source_zip -d $build_dir`)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

# 5. Find the actual source root: a directory that contains CMakeLists.txt
@info "Locating source root..."
function find_cmakelists_root(dir)
# Check if dir itself contains CMakeLists.txt
if isfile(joinpath(dir, "CMakeLists.txt"))
return dir
end
# Otherwise, look for a subdirectory that contains it
for entry in readdir(dir)
path = joinpath(dir, entry)
if isdir(path) && isfile(joinpath(path, "CMakeLists.txt"))
return path
end
end
# If not found, search recursively (but be careful with deep structures)
for (root, dirs, files) in walkdir(dir)
if "CMakeLists.txt" in files
return root
end
end
error("Could not find CMakeLists.txt anywhere in $dir")
end

source_root = find_cmakelists_root(extract_dir)
@info "Source root found at: $source_root"

# 6. Prepare for CMake build: create a build subdirectory inside source_root
build_subdir = joinpath(source_root, "build")
mkpath(build_subdir)
cd(build_subdir) do
# 7. Configure with CMake - build shared library
@info "Configuring with CMake..."
run(`cmake .. -DCOOLPROP_SHARED_LIBRARY=ON -DCMAKE_BUILD_TYPE=Release`)

# 8. Build
@info "Compiling CoolProp (this may take a few minutes)..."
run(`cmake --build . --config Release --parallel $(Sys.CPU_THREADS)`)
end

# 9. Locate the generated shared library
# The library is typically in build/ or build/Release/ or build/lib/
possible_paths = [
joinpath(source_root, "build", lib_name),
joinpath(source_root, "build", "Release", lib_name),
joinpath(source_root, "build", "lib", lib_name),
]

lib_path = nothing
for p in possible_paths
if isfile(p)
lib_path = p
break
end
end

if lib_path === nothing
error("Could not find compiled library. Looked in: $(join(possible_paths, ", "))")
end

@info "CoolProp library built successfully at: $lib_path"
return lib_path
end

struct CompileCoolPropFromSourceforge end

function use_dev_library(::CompileCoolPropFromSourceforge)
lib_src = compile_from_sourceforge()
set_preferences!(CoolProp_jll,"coolprop_library" => lib_src, force = true)
@info "Preference set to $lib_src"
end

function use_dev_library(lib_src::String)
set_preferences!(CoolProp_jll,"coolprop_library" => lib_src, force = true,active_project_only = false,export_prefs = true)
@info "Preference set to $lib_src"
end
Comment thread
longemen3000 marked this conversation as resolved.

function use_default_library()
delete_preferences!(CoolProp_jll,"coolprop_library",force = true,export_prefs = true)
end

end #module
Loading