Skip to content
Open
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
127 changes: 127 additions & 0 deletions .github/workflows/benchmark.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
name: Performance Benchmark
on:
pull_request:
types: [opened, synchronize, reopened]
paths-ignore:
- '*.md'
- '.github/workflows/*'
workflow_call:
inputs:
after_image:
required: true
type: string
before_image:
required: false
type: string

concurrency:
group: benchmark-${{ github.ref }}
cancel-in-progress: true

jobs:
benchmark:
runs-on: ubuntu-large
permissions:
pull-requests: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.25"

- name: Install Kind
run: |
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.27.0/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind

- name: Install Helm
run: |
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
Comment on lines +38 to +46
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

Pin and verify the bootstrap downloads.

kind is fetched as a raw binary and Helm is installed by piping a script from Helm's main branch straight into bash. That makes this job non-reproducible and opens a supply-chain hole on a workflow that has PR write permissions. Prefer versioned, checksum-verified artifacts or pinned setup actions.

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

In @.github/workflows/benchmark.yaml around lines 38 - 46, The workflow
currently downloads kind from
https://kind.sigs.k8s.io/dl/v0.27.0/kind-linux-amd64 and pipes Helm's installer
from https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
directly in the "Install Kind" and "Install Helm" steps; replace these with
pinned, verifiable installs: for the "Install Kind" step either use a maintained
setup action (e.g., actions/setup-kind@vX) or download the tagged release asset
and verify it against a trusted SHA256 checksum before installing; for the
"Install Helm" step use a pinned setup action (e.g., azure/setup-helm@vX or
another official action) or call the Helm install script from a specific release
tag (not main) and verify its checksum/signature, ensuring both steps log
failures and do not pipe unverified scripts into bash.


- name: Resolve before image
id: before-image
env:
GH_TOKEN: ${{ github.token }}
run: |
if [[ -n "${{ inputs.before_image }}" ]]; then
echo "BEFORE_IMAGE=${{ inputs.before_image }}" >> "$GITHUB_OUTPUT"
else
LATEST_TAG=$(gh api repos/${{ github.repository }}/releases/latest --jq '.tag_name')
echo "BEFORE_IMAGE=quay.io/kubescape/node-agent:${LATEST_TAG}" >> "$GITHUB_OUTPUT"
fi

- name: Build after image
id: after-image
if: ${{ !inputs.after_image }}
run: |
curl https://github.com/inspektor-gadget/inspektor-gadget/releases/download/v0.48.1/ig_0.48.1_amd64.deb -LO && sudo dpkg -i ig_0.48.1_amd64.deb
make gadgets
make binary
make docker-build IMAGE=quay.io/kubescape/node-agent TAG=bench-${{ github.sha }}
echo "AFTER_IMAGE=quay.io/kubescape/node-agent:bench-${{ github.sha }}" >> "$GITHUB_OUTPUT"

- name: Set after image from input
id: after-image-input
if: ${{ inputs.after_image }}
run: |
echo "AFTER_IMAGE=${{ inputs.after_image }}" >> "$GITHUB_OUTPUT"

- name: Determine after image
id: resolve-after
run: |
AFTER="${{ steps.after-image.outputs.AFTER_IMAGE || steps.after-image-input.outputs.AFTER_IMAGE }}"
echo "AFTER_IMAGE=${AFTER}" >> "$GITHUB_OUTPUT"

- name: Load after image into Kind
if: ${{ !inputs.after_image }}
run: |
# Kind cluster is created by dedup-bench.sh, but we need to pre-load the image
# The script's load_image function handles this automatically
echo "After image will be loaded by dedup-bench.sh"

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Install Python dependencies
run: pip install -r benchmark/requirements.txt

- name: Run benchmark
env:
BEFORE_IMAGE: ${{ steps.before-image.outputs.BEFORE_IMAGE }}
AFTER_IMAGE: ${{ steps.resolve-after.outputs.AFTER_IMAGE }}
OUTPUT_DIR: ${{ github.workspace }}/benchmark-output
run: |
chmod +x benchmark/dedup-bench.sh
benchmark/dedup-bench.sh "$BEFORE_IMAGE" "$AFTER_IMAGE"

- name: Generate markdown report
if: always()
run: |
python3 benchmark/compare-metrics.py --format markdown \
"${{ github.workspace }}/benchmark-output/before" \
"${{ github.workspace }}/benchmark-output/after" > report.md || true

- name: Comment on PR
uses: peter-evans/create-or-update-comment@v4
if: github.event_name == 'pull_request' && always()
with:
issue-number: ${{ github.event.pull_request.number }}
body-path: report.md
comment-tag: benchmark-results
Comment on lines +113 to +119
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 "action.yml" -o -name "action.yaml" | head -20

Repository: kubescape/node-agent

Length of output: 46


🏁 Script executed:

# Check the benchmark.yaml file
cat -n .github/workflows/benchmark.yaml | sed -n '110,125p'

Repository: kubescape/node-agent

Length of output: 755


🏁 Script executed:

# Fetch the action.yml from peter-evans/create-or-update-comment@v4
curl -s https://raw.githubusercontent.com/peter-evans/create-or-update-comment/v4/action.yml | head -100

Repository: kubescape/node-agent

Length of output: 1533


🏁 Script executed:

# Search for information about fork PRs and GITHUB_TOKEN
curl -s https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions 2>/dev/null | grep -i fork || echo "Need web search"

Repository: kubescape/node-agent

Length of output: 79


🏁 Script executed:

# Also check if find-comment action exists
curl -s https://raw.githubusercontent.com/peter-evans/find-comment/main/action.yml 2>/dev/null | head -50

Repository: kubescape/node-agent

Length of output: 1370


🏁 Script executed:

# Verify the fork PR + GITHUB_TOKEN restriction
curl -s https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows | grep -A 5 "fork" | head -20 || echo "Checking GitHub Actions documentation about fork restrictions..."

Repository: kubescape/node-agent

Length of output: 46


🏁 Script executed:

# Check if there are any recent issues or documentation about fork PRs and GITHUB_TOKEN
curl -s https://api.github.com/repos/peter-evans/create-or-update-comment/issues?state=all&per_page=5 2>/dev/null | head -50

Repository: kubescape/node-agent

Length of output: 46


🏁 Script executed:

# Check the README or docs in the action repo
curl -s https://raw.githubusercontent.com/peter-evans/create-or-update-comment/v4/README.md | grep -A 10 -B 5 "fork\|permission\|GITHUB_TOKEN" | head -40

Repository: kubescape/node-agent

Length of output: 2913


Remove the unsupported comment-tag input and implement a sticky comment strategy.

The create-or-update-comment@v4 action does not have a comment-tag input—it supports issue-number, comment-id, body/body-path, and edit-mode. The comment-tag parameter will be silently ignored, causing the action to create a new comment on each run instead of updating a sticky one.

Additionally, this action cannot post comments in public repositories when triggered by fork PRs; attempting this will result in Resource not accessible by integration. Use the find-comment action to locate an existing comment by body-includes and pass its comment-id to create-or-update-comment, or switch to the pull_request_target event as documented in the action README.

🧰 Tools
🪛 actionlint (1.7.12)

[error] 119-119: input "comment-tag" is not defined in action "peter-evans/create-or-update-comment@v4". available inputs are "append-separator", "body", "body-file", "body-path", "comment-id", "edit-mode", "issue-number", "reactions", "reactions-edit-mode", "repository", "token"

(action)

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

In @.github/workflows/benchmark.yaml around lines 113 - 119, The workflow uses
peter-evans/create-or-update-comment@v4 with an unsupported input `comment-tag`,
causing new comments each run; remove `comment-tag` and implement a
sticky-comment flow by first using an action like peter-evans/find-comment to
search for the existing comment via `body-includes` (e.g., matching text from
`report.md`), capture its `comment-id`, then pass that `comment-id` into
create-or-update-comment (or use `edit-mode`) along with `body-path: report.md`
and `issue-number` to update the existing comment; alternatively, switch the job
trigger to `pull_request_target` to avoid fork PR permission issues as
documented in the create-or-update-comment README.


- name: Upload artifacts
uses: actions/upload-artifact@v4
if: always()
with:
name: benchmark-results
path: ${{ github.workspace }}/benchmark-output/
retention-days: 30
8 changes: 8 additions & 0 deletions .github/workflows/incluster-comp-pr-merged.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,14 @@ jobs:
path: failed_*.txt
retention-days: 7

benchmark:
needs: docker-build
if: ${{ contains(github.event.pull_request.labels.*.name, 'release') }}
uses: ./.github/workflows/benchmark.yaml
with:
after_image: ${{ inputs.IMAGE_NAME }}:${{ needs.docker-build.outputs.IMAGE_TAG_PRERELEASE }}
secrets: inherit

create-release-and-retag:
if: ${{ contains(github.event.pull_request.labels.*.name, 'release') && always() && contains(needs.*.result, 'success') && !(contains(needs.*.result, 'failure')) && !(contains (needs.*.result,'cancelled')) || inputs.FORCE }}
name: Docker retag and create release
Expand Down
Loading
Loading