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
210 changes: 210 additions & 0 deletions .github/workflows/perf-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
name: perf-test

on:
issue_comment:
types: [created]

jobs:
perf-test:
if: github.event.comment.body == '/perf-test' && github.event.issue.pull_request != null
runs-on: ubuntu-24.04

steps:

- name: Check if Commenter is a Collaborator
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COMMENTER: ${{ github.event.comment.user.login }}
REPO: ${{ github.repository }}
run: |
PERMISSIONS=$(gh api repos/$REPO/collaborators/$COMMENTER/permission --jq '.permission')
echo "User Permission: $PERMISSIONS"

if [[ "$PERMISSIONS" != "admin" && "$PERMISSIONS" != "write" && "$PERMISSIONS" != "maintain" ]]; then
echo "❌ User does not have permission to trigger this action."
exit 1
fi

- name: Acknowledge Command
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
COMMENT_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"

gh api repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/comments \
-f body="🛠️ Perf test has started! Follow the progress here: [Workflow Run]($COMMENT_URL)"

- name: Maximize build space
run: |
df -h
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/local/lib/android
sudo rm -rf /opt/ghc
sudo rm -rf /opt/hostedtoolcache/CodeQL
sudo docker image prune --all --force
sudo rm -Rf ${JAVA_HOME_8_X64}
sudo rm -Rf ${JAVA_HOME_11_X64}
sudo rm -Rf ${JAVA_HOME_17_X64}
sudo rm -Rf ${RUBY_PATH}
df -h

- name: Get PR head ref
id: pr
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PR_JSON=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.issue.number }})
HEAD_SHA=$(echo "$PR_JSON" | jq -r '.head.sha')
HEAD_REF=$(echo "$PR_JSON" | jq -r '.head.ref')
echo "sha=$HEAD_SHA" >> "$GITHUB_OUTPUT"
echo "ref=$HEAD_REF" >> "$GITHUB_OUTPUT"

- uses: actions/checkout@v5
with:
ref: ${{ steps.pr.outputs.sha }}

- uses: ./.github/actions/setup-rust
- uses: Swatinem/rust-cache@v2

- name: Setup cargo-binstall
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash

- name: Install oidc CLI
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
cargo binstall -y --force oidc-cli

- name: Install HTTPie
run: |
python -m pip install --upgrade pip wheel
python -m pip install httpie

- name: Install uv
uses: astral-sh/setup-uv@v6

- name: Build
run: |
cargo build --bin trustd --release

- name: Start trustd
env:
NO_COLOR: "true"
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run:
nohup cargo run --bin trustd --release &> trustd.log &

- name: Wait for the backend to be up
run: |
URL="http://localhost:8080/.well-known/trustify"
TIMEOUT=300 # 5 minutes
INTERVAL=5 # Interval between retries in seconds
START_TIME=$(date +%s)

while true; do
# Check if the endpoint is up
if curl -s --fail "$URL"; then
echo
echo "Endpoint is up!"
exit 0
fi

# Check if timeout has passed
CURRENT_TIME=$(date +%s)
ELAPSED_TIME=$((CURRENT_TIME - START_TIME))

if [ "$ELAPSED_TIME" -ge "$TIMEOUT" ]; then
echo "Timeout reached. Endpoint is still down."
exit 1
fi

echo "Endpoint is down. Retrying in $INTERVAL seconds..."
sleep "$INTERVAL"
done

- name: Setup OIDC
run: |
oidc create confidential trustify --issuer http://localhost:8090/realms/trustify --client-id walker --client-secret R8A6KFeyxJsMDBhjfHbpZTIF0GWt43HP --force # no-secret

- name: Ingest DS3 dataset
run: |
.github/scripts/benchmark.sh

- name: Run perf tests
working-directory: tools/perf
env:
TOOLS_PERF_SCENARIO_FILE: etc/scenarios/empty.json5
run: |
uv run locust \
--host http://localhost:8080 \
-u 10 -r 2 -t 5m \
--headless \
--html=report.html \
--csv=results

- name: Upload trustd logs
uses: actions/upload-artifact@v7
if: always()
with:
name: logs
path: |
trustd.log
if-no-files-found: error

- name: Upload perf report
uses: actions/upload-artifact@v7
if: always()
with:
name: report
path: |
tools/perf/report.html
tools/perf/results_*.csv
if-no-files-found: warn

- name: Post comment
if: always()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
ARTIFACT_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"

if [ -f tools/perf/results_stats.csv ]; then
# Build a markdown table from the CSV stats
STATS_TABLE=$(python3 -c "
import csv, io, sys
with open('tools/perf/results_stats.csv') as f:
reader = csv.reader(f)
rows = list(reader)
if not rows:
sys.exit(0)
header = rows[0]
# Select useful columns: Type, Name, # Requests, # Failures,
# Median, Average, Min, Max, Avg size, RPS
cols = [0, 1, 2, 3, 5, 6, 7, 8, 9, 10]
hdr = [header[c] for c in cols]
print('| ' + ' | '.join(hdr) + ' |')
print('| ' + ' | '.join(['---'] * len(hdr)) + ' |')
for row in rows[1:]:
vals = [row[c] if c < len(row) else '' for c in cols]
print('| ' + ' | '.join(vals) + ' |')
")
else
STATS_TABLE="No stats CSV produced."
fi

COMMENT_BODY=$(cat <<__EOF__
<details><summary>Perf Test Report (Locust)</summary>

$STATS_TABLE

</details>

📄 **[Full Report]($ARTIFACT_URL)** (Go to "Artifacts" and download **report**)

__EOF__
)
gh api repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/comments \
-f body="$COMMENT_BODY"
2 changes: 2 additions & 0 deletions common/src/db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,7 @@ impl ReadOnly {
}

/// Begins a read-only transaction.
#[instrument(skip(self), err(level=tracing::Level::INFO))]
pub async fn begin(&self) -> Result<DatabaseTransaction, DbError> {
Ok(self
.0
Expand All @@ -634,6 +635,7 @@ impl ReadOnly {
/// Begins a read-only transaction with the given isolation level.
///
/// The access mode is always forced to `ReadOnly`; passing `ReadWrite` returns an error.
#[instrument(skip(self), err(level=tracing::Level::INFO))]
pub async fn begin_with_config(
&self,
isolation_level: Option<IsolationLevel>,
Expand Down
161 changes: 161 additions & 0 deletions etc/test-data/csaf/cve-2023-0044-multi-score.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
{
"document": {
"aggregate_severity": {
"namespace": "https://access.redhat.com/security/updates/classification/",
"text": "low"
},
"category": "csaf_vex",
"csaf_version": "2.0",
"distribution": {
"text": "Copyright © Red Hat, Inc. All rights reserved.",
"tlp": {
"label": "WHITE",
"url": "https://www.first.org/tlp/"
}
},
"lang": "en",
"notes": [
{
"category": "description",
"text": "Synthetic CSAF advisory created for trustify integration tests. Derived from cve-2023-0044.json with an additional CVSS v2 score to test multi-score deduplication.",
"title": "Test Data"
}
],
"publisher": {
"category": "other",
"contact_details": "https://github.com/guacsec/trustify",
"issuing_authority": "Synthetic test data — not a real advisory.",
"name": "trustify test suite",
"namespace": "https://github.com/guacsec/trustify"
},
"references": [
{
"category": "self",
"summary": "Canonical URL",
"url": "https://access.redhat.com/security/data/csaf/beta/vex/2023/cve-2023-0044-multi-score.json"
}
],
"title": "quarkus-vertx-http: multi-score test variant",
"tracking": {
"current_release_date": "2023-11-13T11:31:31+00:00",
"generator": {
"date": "2023-11-13T12:16:30+00:00",
"engine": {
"name": "trustify test suite (synthetic)",
"version": "0.0.0"
}
},
"id": "CVE-2023-0044-multi-score",
"initial_release_date": "2023-01-04T00:00:00+00:00",
"revision_history": [
{
"date": "2023-01-04T00:00:00+00:00",
"number": "1",
"summary": "Initial version"
}
],
"status": "final",
"version": "1"
}
},
"product_tree": {
"branches": [
{
"branches": [
{
"category": "product_name",
"name": "Red Hat build of Quarkus",
"product": {
"name": "Red Hat build of Quarkus",
"product_id": "red_hat_build_of_quarkus",
"product_identification_helper": {
"cpe": "cpe:/a:redhat:quarkus:2"
}
}
},
{
"category": "product_version",
"name": "io.quarkus/quarkus-vertx-http",
"product": {
"name": "io.quarkus/quarkus-vertx-http",
"product_id": "io.quarkus/quarkus-vertx-http"
}
}
],
"category": "vendor",
"name": "Red Hat"
}
],
"relationships": [
{
"category": "default_component_of",
"full_product_name": {
"name": "io.quarkus/quarkus-vertx-http as a component of Red Hat build of Quarkus",
"product_id": "red_hat_build_of_quarkus:io.quarkus/quarkus-vertx-http"
},
"product_reference": "io.quarkus/quarkus-vertx-http",
"relates_to_product_reference": "red_hat_build_of_quarkus"
}
]
},
"vulnerabilities": [
{
"cve": "CVE-2023-0044",
"discovery_date": "2023-01-04T00:00:00+00:00",
"product_status": {
"known_affected": [
"red_hat_build_of_quarkus:io.quarkus/quarkus-vertx-http"
]
},
"references": [
{
"category": "self",
"summary": "Canonical URL",
"url": "https://access.redhat.com/security/cve/CVE-2023-0044"
}
],
"release_date": "2023-01-04T00:00:00+00:00",
"remediations": [
{
"category": "none_available",
"details": "Affected",
"product_ids": [
"red_hat_build_of_quarkus:io.quarkus/quarkus-vertx-http"
]
}
],
"scores": [
{
"cvss_v3": {
"attackComplexity": "LOW",
"attackVector": "NETWORK",
"availabilityImpact": "NONE",
"baseScore": 5.3,
"baseSeverity": "MEDIUM",
"confidentialityImpact": "LOW",
"integrityImpact": "NONE",
"privilegesRequired": "NONE",
"scope": "UNCHANGED",
"userInteraction": "NONE",
"vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N",
"version": "3.1"
},
"products": [
"red_hat_build_of_quarkus:io.quarkus/quarkus-vertx-http"
]
},
{
"cvss_v2": {
"baseScore": 3.5,
"vectorString": "AV:N/AC:M/Au:S/C:P/I:N/A:N",
"version": "2.0"
},
"products": [
"red_hat_build_of_quarkus:io.quarkus/quarkus-vertx-http"
]
}
],
"title": "quarkus-vertx-http: multi-score test"
}
]
}
Loading
Loading