Skip to content

Enable OpenWhisk in CI#302

Merged
mcopik merged 23 commits intomasterfrom
feature/test-ci-whisk
May 2, 2026
Merged

Enable OpenWhisk in CI#302
mcopik merged 23 commits intomasterfrom
feature/test-ci-whisk

Conversation

@mcopik
Copy link
Copy Markdown
Collaborator

@mcopik mcopik commented May 2, 2026

As title suggests - deploy OW on kind in GitHub runners, testing one more platform for correctness and compatibility.

Summary by CodeRabbit

  • New Features

    • Added end-to-end regression testing workflow for OpenWhisk deployments
    • Enabled container image URI support for function deployment
  • Bug Fixes

    • Implemented missing Minio download functionality
    • Fixed cache handling for new deployment configurations
  • Chores

    • Updated default Python runtime from 3.6 to 3.11
    • Enhanced OpenWhisk and Minio storage configuration options

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 2, 2026

Warning

Rate limit exceeded

@mcopik has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 41 minutes and 47 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3ea0fe1d-ac9e-4a13-8851-fc11819a402c

📥 Commits

Reviewing files that changed from the base of the PR and between 57fb531 and 1032a7f.

📒 Files selected for processing (2)
  • .github/workflows/regression-whisk.yml
  • benchmarks/wrappers/openwhisk/nodejs/index.js
📝 Walkthrough

Walkthrough

This PR adds OpenWhisk regression testing infrastructure via a new CI workflow that provisions a Kind Kubernetes cluster with local Docker registry and SeBS-backed storage, deploys OpenWhisk, and runs regression benchmarks. Supporting code updates enable container URI override for function deployment, implement MinIO download, fix storage configuration lookups, and adjust function wrapper formats across multiple runtimes.

Changes

OpenWhisk Regression Testing Pipeline

Layer / File(s) Summary
Deployment Configuration
configs/openwhisk.json
Python runtime updated from 3.6 to 3.11; added architecture, system_variant, docker_registry, and storage objects with MinIO configuration.
Regression Workflow
.github/workflows/regression-whisk.yml
New end-to-end CI job that provisions Kind cluster with Docker registry, deploys OpenWhisk via Helm, configures SeBS storage, runs sebs benchmark regression test across Python/Node/Java runtimes, collects diagnostics on failure, uploads artifacts, and cleans up infrastructure.

Storage Configuration & Implementation

Layer / File(s) Summary
Cache Handling
sebs/cache.py
add_code_package now initializes missing deployment_name entries in cached config before attempting to access them.
Storage Implementation
sebs/storage/minio.py
download() method implemented: validates bucket existence and downloads via MinIO client instead of raising NotImplementedError.
Configuration Lookup
sebs/storage/resources.py
_deserialize_storage now uses dynamic cached_config["resources"]["storage"][storage_type] lookup instead of hardcoded cached_config["storage"]["object"].

OpenWhisk Function Deployment

Layer / File(s) Summary
Container URI Preference
sebs/openwhisk/openwhisk.py
create_function and update_function now prefer passed container_uri parameter for --docker argument; fall back to computed benchmark image name when container_uri is None.

Function Wrapper Updates

Layer / File(s) Summary
Response Format
benchmarks/wrappers/openwhisk/java/.../Handler.java
Response JSON now writes result directly as an object instead of nesting it within a logData wrapper.
Environment Variable Access
benchmarks/wrappers/openwhisk/nodejs/nosql.js
NOSQL_STORAGE_TYPE environment variable accessed via bracket notation instead of dot notation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • Run regression on CI #294: Adds/modifies OpenWhisk CI workflows and regression testing configuration in a related infrastructure update.

Poem

🐰 A cluster springs forth from the Kind,
With registries and storage aligned,
Functions now take the container they choose,
While storage downloads—no longer to lose,
Regression tests dance through the cloud! 🌟

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Enable OpenWhisk in CI' directly and clearly summarizes the main change: adding OpenWhisk integration to the CI pipeline via the new regression-whisk workflow and supporting configuration updates.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/test-ci-whisk

Tip

💬 Introducing Slack Agent: Turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get your free trial and get 200 agent minutes per Slack user (a $50 value).


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 41 minutes and 47 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/regression-whisk.yml:
- Around line 224-242: The failure diagnostics step ("Diagnostics on failure")
can fail if the diagnostics/ directory doesn't exist when earlier setup steps
failed; modify the run block for that step to ensure the directory exists before
writing logs by adding a command such as mkdir -p diagnostics (or equivalent)
prior to the block that pipes output into tee
diagnostics/cluster-diagnostics.txt so the kubectl/curl/docker output can always
be written.
- Around line 123-130: The git clone in the workflow currently pulls the default
branch which makes CI brittle; update the git clone command (the line starting
with "git clone --depth 1 https://github.com/apache/openwhisk-deploy-kube.git
/tmp/ow") to pin a stable tag or branch by adding --branch <TAG> (for example
--branch 1.0.0) so it clones a specific release (keep --depth 1 for shallow
clone); this ensures the subsequent sed patch against values.yaml and the helm
install using /tmp/ow/helm/openwhisk remain reproducible.

In @.github/workflows/regression.yml:
- Around line 4-7: The regression workflow accidentally disables the automatic
regression matrix by commenting out the push trigger; restore automatic coverage
by re-enabling the push trigger (uncomment or re-add the "push:" block and its
branch filters) in .github/workflows/regression.yml so that branches "master"
and "feature/**" will trigger regressions again, and ensure the new
regression-whisk.yml remains additive (it should add OpenWhisk coverage but not
replace the original push-triggered AWS/GCP/Azure jobs).

In `@configs/openwhisk.json`:
- Around line 28-37: The storage block was flattened but
SelfHostedSystemResources._deserialize_storage() expects storage.object.type and
storage.object.minio; update the JSON so the storage entry nests under an
"object" key with a "type" and a "minio" object (e.g., storage.object.type =
"minio" and storage.object.minio = {
"address","mapped_port","access_key","secret_key","instance_id","input_buckets","output_buckets"
}) so the deserializer in SelfHostedSystemResources._deserialize_storage() can
find storage.object.type and storage.object.minio.

In `@sebs/storage/minio.py`:
- Around line 413-416: The except block binds an unused variable which triggers
lint failure; update the handler in the block around self.connection.fget_object
to either remove the try/except entirely or change the clause from "except
minio.error.ResponseError as err:" to "except minio.error.ResponseError:" so the
exception is still re-raised but no unused name is bound (keep the current
re-raise behavior).
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: eb33e970-3f61-4f20-997c-fc2956ede71e

📥 Commits

Reviewing files that changed from the base of the PR and between 621ba5c and 60f1ed4.

📒 Files selected for processing (6)
  • .github/workflows/regression-whisk.yml
  • .github/workflows/regression.yml
  • configs/openwhisk.json
  • sebs/cache.py
  • sebs/openwhisk/openwhisk.py
  • sebs/storage/minio.py

Comment thread .github/workflows/regression-whisk.yml
Comment thread .github/workflows/regression-whisk.yml
Comment thread .github/workflows/regression.yml Outdated
Comment thread configs/openwhisk.json
Comment thread sebs/storage/minio.py Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
sebs/storage/resources.py (1)

138-145: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Cached storage lookup no longer matches how the cache is written.

update_cache() in this file writes MinIO under resources.storage.* and ScyllaDB under resources.nosql.*, but this branch now reads resources.storage[storage_type]. That means the object path misses the cached MinIO shape, and the nosql path can dereference a key that is never written. This will break deserialization from cache after a prior update_cache() run.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sebs/storage/resources.py` around lines 138 - 145, The cached lookup is using
resources.storage[storage_type] but update_cache() writes MinIO under
resources.storage and ScyllaDB under resources.nosql, so adjust the branch that
sets storage_impl and storage_config to read the correct cache shape based on
storage_type: for object storage (storage_type == "object") read
cached_config["resources"]["storage"]["object"] and derive
storage_impl/storage_config from that structure (e.g. MinIO), and for nosql
storage (storage_type == "nosql") read cached_config["resources"]["nosql"] to
find the nosql implementation and its config; update the code that assigns
storage_impl and storage_config (the variables storage_impl, storage_config and
the cached_config checks) so they match the keys written by update_cache().
🧹 Nitpick comments (1)
.github/workflows/regression-whisk.yml (1)

63-68: ⚡ Quick win

Pin kubectl to the Kind cluster minor instead of stable.txt.

This job fixes the cluster at kindest/node:v1.31.4 but lets kubectl float to whatever upstream marks as stable. Once that drifts far enough, the workflow can start failing without any repo change. Pinning kubectl to the same Kubernetes minor keeps this CI path reproducible.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/regression-whisk.yml around lines 63 - 68, The workflow
currently downloads kubectl using stable.txt (KCTL=$(curl -fsSL
https://dl.k8s.io/release/stable.txt)), which lets kubectl float; change this to
pin kubectl to the same Kubernetes minor as the Kind node image used by the job
(use the same version variable or literal used for the Kind image, e.g.,
KIND_NODE_VERSION or the v1.31.4 value) so KCTL is set to that specific release
string and the curl/download step fetches that pinned release; update the
kubectl install block that defines KCTL and the download URL accordingly to
ensure kubectl matches the Kind cluster minor.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/regression-whisk.yml:
- Around line 134-137: The WORKER_IP extraction uses an index-based JSONPath
which can pick the wrong address; update the kubectl command that sets WORKER_IP
to explicitly filter for the InternalIP type (use a JSONPath filter selecting
addresses where type=="InternalIP") so the WORKER_IP variable is always the node
InternalIP; keep the rest of the lines (HOST_IP and exporting to GITHUB_ENV)
unchanged.

---

Outside diff comments:
In `@sebs/storage/resources.py`:
- Around line 138-145: The cached lookup is using
resources.storage[storage_type] but update_cache() writes MinIO under
resources.storage and ScyllaDB under resources.nosql, so adjust the branch that
sets storage_impl and storage_config to read the correct cache shape based on
storage_type: for object storage (storage_type == "object") read
cached_config["resources"]["storage"]["object"] and derive
storage_impl/storage_config from that structure (e.g. MinIO), and for nosql
storage (storage_type == "nosql") read cached_config["resources"]["nosql"] to
find the nosql implementation and its config; update the code that assigns
storage_impl and storage_config (the variables storage_impl, storage_config and
the cached_config checks) so they match the keys written by update_cache().

---

Nitpick comments:
In @.github/workflows/regression-whisk.yml:
- Around line 63-68: The workflow currently downloads kubectl using stable.txt
(KCTL=$(curl -fsSL https://dl.k8s.io/release/stable.txt)), which lets kubectl
float; change this to pin kubectl to the same Kubernetes minor as the Kind node
image used by the job (use the same version variable or literal used for the
Kind image, e.g., KIND_NODE_VERSION or the v1.31.4 value) so KCTL is set to that
specific release string and the curl/download step fetches that pinned release;
update the kubectl install block that defines KCTL and the download URL
accordingly to ensure kubectl matches the Kind cluster minor.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9060557a-3241-4be5-afd7-f9b017cb88c5

📥 Commits

Reviewing files that changed from the base of the PR and between 60f1ed4 and 57fb531.

📒 Files selected for processing (6)
  • .github/workflows/regression-whisk.yml
  • benchmarks/wrappers/openwhisk/java/src/main/java/org/serverlessbench/Handler.java
  • benchmarks/wrappers/openwhisk/nodejs/nosql.js
  • configs/openwhisk.json
  • sebs/storage/minio.py
  • sebs/storage/resources.py
✅ Files skipped from review due to trivial changes (1)
  • benchmarks/wrappers/openwhisk/nodejs/nosql.js

Comment on lines +134 to +137
WORKER_IP=$(kubectl get node kind-worker -o jsonpath='{.status.addresses[0].address}')
HOST_IP=$(hostname -I | awk '{print $1}')
echo "WORKER_IP=${WORKER_IP}" >> $GITHUB_ENV
echo "HOST_IP=${HOST_IP}" >> $GITHUB_ENV
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

🌐 Web query:

Kubernetes node address ordering guarantee status.addresses

💡 Result:

Kubernetes does not provide a general, stable ordering guarantee for Node.status.addresses. What Kubernetes actually guarantees/does: 1) Order can change for reasons outside your control (e.g., multiple addresses of the same type and how kubelet updates Node.Status). Historically kubelet could reorder Node.Status.Addresses when multiple addresses of the same type changed; Kubernetes fixed this by ensuring kubelet updates use a replace strategy for NodeStatus.Addresses (to avoid random reordering that could change the “primary” address). 2) Consumers are expected to pick an address by type (and often by a preference list), not by assuming list position. - GetPreferredNodeAddress iterates Node.Status.Addresses and returns the first entry whose Type matches the preferred types list; it does not define/require a particular overall list order. - The helper GetNodeHostIPs explicitly re-sorts internally: it moves all NodeInternalIP entries first, then NodeExternalIP, and then chooses a “primary” first IP; it does not rely on the original addresses list ordering. - kubelet’s nodestatus setters build Node.Status.Addresses with a specific order (e.g., InternalIP then Hostname) in the path shown, but this is implementation detail and depends on which fields are being set. Practical recommendation: - Never rely on Node.status.addresses[i] ordering. - Select by NodeAddress.Type (Hostname/InternalIP/ExternalIP, etc.) and/or use Kubernetes helpers like nodeutil.GetPreferredNodeAddress (in kubelet code) or apply your own preference rules. Bottom line: There is no “status.addresses ordering guarantee” you can depend on; order is not a contract. If you need determinism, sort/reselect by address type yourself or use Kubernetes’ address-selection logic.

Citations:


🌐 Web query:

kubectl jsonpath filter InternalIP address syntax

💡 Result:

kubectl jsonpath filter for InternalIP on Node objects: kubectl get nodes -o jsonpath='{.items[].status.addresses[?(@.type=="InternalIP")].address}' Notes on syntax: - The filter uses the ? JSONPath filter syntax: [?()]. - @ refers to the current array element being filtered. - Quote the string literal (InternalIP). Example (human-readable with newline): kubectl get nodes -o jsonpath='{range .items[]}{range .status.addresses[?(@.type=="InternalIP")]}{.address}{"\n"}{end}{end}'

Citations:


🏁 Script executed:

# Let's also verify if this specific jsonpath syntax is valid
# by checking for examples in common tools and documentation
cat <<'EOF'
Testing JSONPath filter syntax for Kubernetes node addresses
EOF

Repository: spcl/serverless-benchmarks

Length of output: 131


🏁 Script executed:

# Check the workflow file for context around how WORKER_IP is used
head -n 150 .github/workflows/regression-whisk.yml | tail -n 30

Repository: spcl/serverless-benchmarks

Length of output: 1375


🏁 Script executed:

# Also check if there are other similar patterns in the file that might need the same fix
rg 'status\.addresses\[0\]' .github/workflows/

Repository: spcl/serverless-benchmarks

Length of output: 206


Select the node InternalIP explicitly instead of relying on address ordering.

{.status.addresses[0].address} assumes a stable address order, but Kubernetes does not guarantee this. If Hostname lands first in the list, wsk --apihost will be configured with the wrong value and tests will fail. Use a JSONPath filter to explicitly select the InternalIP type.

Suggested fix
-          WORKER_IP=$(kubectl get node kind-worker -o jsonpath='{.status.addresses[0].address}')
+          WORKER_IP=$(kubectl get node kind-worker -o jsonpath='{.status.addresses[?(@.type=="InternalIP")].address}')
📝 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
WORKER_IP=$(kubectl get node kind-worker -o jsonpath='{.status.addresses[0].address}')
HOST_IP=$(hostname -I | awk '{print $1}')
echo "WORKER_IP=${WORKER_IP}" >> $GITHUB_ENV
echo "HOST_IP=${HOST_IP}" >> $GITHUB_ENV
WORKER_IP=$(kubectl get node kind-worker -o jsonpath='{.status.addresses[?(@.type=="InternalIP")].address}')
HOST_IP=$(hostname -I | awk '{print $1}')
echo "WORKER_IP=${WORKER_IP}" >> $GITHUB_ENV
echo "HOST_IP=${HOST_IP}" >> $GITHUB_ENV
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/regression-whisk.yml around lines 134 - 137, The WORKER_IP
extraction uses an index-based JSONPath which can pick the wrong address; update
the kubectl command that sets WORKER_IP to explicitly filter for the InternalIP
type (use a JSONPath filter selecting addresses where type=="InternalIP") so the
WORKER_IP variable is always the node InternalIP; keep the rest of the lines
(HOST_IP and exporting to GITHUB_ENV) unchanged.

@mcopik mcopik merged commit a7a0532 into master May 2, 2026
18 checks passed
@mcopik mcopik deleted the feature/test-ci-whisk branch May 2, 2026 21:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant