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
58 changes: 58 additions & 0 deletions benchmark/stress/prepare_data.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/bin/bash
# Copyright The Conforma Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0

# Creates the files in the data directory that should contain all the data
# needed to run the benchmark. Tries to pull a pre-built data archive from Quay
# first, falling back to building from upstream using the ../offliner for images
# and plain git clone for the git data dependency. Uses the same
# golden-container image as the simple benchmark -- the stress benchmark
# duplicates it across components at runtime.
set -o errexit
set -o nounset
set -o pipefail

quay_ref="quay.io/conforma/benchmark-data:stress-v1"

if command -v oras &>/dev/null && oras pull "${quay_ref}" -o . 2>/dev/null; then
echo "Downloaded data.tar.gz from ${quay_ref}"
exit 0
fi

echo "Quay pull failed or oras not available, regenerating from upstream..."

Comment on lines +30 to +36

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 | ⚡ Quick win

Fail closed on Quay pull failures to keep benchmark input deterministic

Line 30 suppresses pull errors and Line 35 always regenerates from upstream on any failure. That makes CI runs non-reproducible and can hide artifact-hosting/auth outages behind a “successful” local rebuild.

Suggested change
-if command -v oras &>/dev/null && oras pull "${quay_ref}" -o . 2>/dev/null; then
+if command -v oras &>/dev/null && oras pull "${quay_ref}" -o .; then
     echo "Downloaded data.tar.gz from ${quay_ref}"
     exit 0
 fi

-echo "Quay pull failed or oras not available, regenerating from upstream..."
+if [[ "${EC_STRESS_ALLOW_REGEN:-0}" != "1" ]]; then
+    echo "Failed to pull ${quay_ref}. Set EC_STRESS_ALLOW_REGEN=1 to regenerate from upstream." >&2
+    exit 1
+fi
+echo "Quay pull failed or oras not available, regenerating from upstream (EC_STRESS_ALLOW_REGEN=1)..."
📝 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 command -v oras &>/dev/null && oras pull "${quay_ref}" -o . 2>/dev/null; then
echo "Downloaded data.tar.gz from ${quay_ref}"
exit 0
fi
echo "Quay pull failed or oras not available, regenerating from upstream..."
if command -v oras &>/dev/null && oras pull "${quay_ref}" -o .; then
echo "Downloaded data.tar.gz from ${quay_ref}"
exit 0
fi
if [[ "${EC_STRESS_ALLOW_REGEN:-0}" != "1" ]]; then
echo "Failed to pull ${quay_ref}. Set EC_STRESS_ALLOW_REGEN=1 to regenerate from upstream." >&2
exit 1
fi
echo "Quay pull failed or oras not available, regenerating from upstream (EC_STRESS_ALLOW_REGEN=1)..."
🤖 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 `@benchmark/stress/prepare_data.sh` around lines 30 - 36, The oras pull command
suppresses error output with 2>/dev/null and the script always falls back to
regenerating from upstream on failure, making CI runs non-reproducible and
hiding infrastructure issues. Remove the error suppression (2>/dev/null) from
the oras pull command on line 30 and restructure the logic so that if the oras
pull fails, the script exits with an error rather than continuing to the
regeneration fallback. This ensures benchmark input remains deterministic and
surfaces any Quay or authentication failures instead of silently working around
them.

offliner="$(git rev-parse --show-toplevel)/benchmark/offliner"

dir="$(mktemp -d)"
trap 'rm -rf "${dir}"' EXIT

(
cd "${dir}"

imgs=(
quay.io/redhat-user-workloads/rhtap-contract-tenant/golden-container/golden-container@sha256:166e38c156fa81d577a7ba7a948b68c79005a06e302779d1bebc7d31e8bea315
quay.io/konflux-ci/tekton-catalog/data-acceptable-bundles@sha256:1e70b8f672388838f20a7d45e145e31e99dab06cefa1c5514d6ce41c8bbea1b0
quay.io/enterprise-contract/ec-release-policy@sha256:64617f0c45689ef7152c5cfbd4cd5709a3126e4ab7482eb6acd994387fe2d4ba
)

for img in "${imgs[@]}"; do
go run -C "${offliner}" . "${img}" "${dir}/data/registry/data"
done

git clone --no-checkout https://github.com/release-engineering/rhtap-ec-policy.git data/git/rhtap-ec-policy.git
)

tar czf data.tar.gz -C "${dir}" .
32 changes: 32 additions & 0 deletions benchmark/stress/push_data.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/bash
# Copyright The Conforma Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0

# Pushes the local data.tar.gz to Quay as an OCI artifact. Requires prior
# authentication via `oras login quay.io`.
set -o errexit
set -o nounset
set -o pipefail

quay_ref="quay.io/conforma/benchmark-data:stress-v1"

if [[ ! -f data.tar.gz ]]; then
echo "data.tar.gz not found, run prepare_data.sh first" >&2
exit 1
fi

oras push "${quay_ref}" data.tar.gz
echo "Pushed data.tar.gz to ${quay_ref}"
178 changes: 178 additions & 0 deletions benchmark/stress/stress.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
// Copyright The Conforma Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

// Stress benchmark validating a multi-component snapshot with a configurable
// number of workers, simulating real-world release pipeline workloads. The
// component count and worker count are controlled via the EC_STRESS_COMPONENTS
// and EC_STRESS_WORKERS environment variables respectively. Uses the same
// golden-container image data as the simple benchmark, duplicated across
// components to create memory pressure. The prepare_data.sh script can be used
// to re-populate the data directory.
package main

import (
"encoding/json"
"fmt"
"os"
"path"
"strconv"

"golang.org/x/benchmarks/driver"

"github.com/conforma/cli/benchmark/internal/registry"
"github.com/conforma/cli/benchmark/internal/suite"
"github.com/conforma/cli/benchmark/internal/untar"
)
Comment on lines +26 to +38

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 | ⚡ Quick win

stress.go is currently failing gci formatting checks

Static analysis reports a gci formatting error (reported at Line 82). Please run the repo’s Go formatting/import-order step for this file to unblock lint/CI.

🤖 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 `@benchmark/stress/stress.go` around lines 26 - 38, The imports in the
stress.go file are not properly ordered according to the gci formatting
standards. Run the project's Go import formatting tool (typically gci write or
go fmt) on the stress.go file to automatically reorder the imports into the
correct grouping: standard library imports first, followed by blank line, then
third-party imports (like golang.org/x/benchmarks), followed by blank line, then
local package imports (like github.com/conforma/cli). This will resolve the gci
formatting check failure.

Source: Linters/SAST tools


const (
defaultComponents = 10
defaultWorkers = 35

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[low] edge-case

The envInt function panics on values < 1 but does not guard against unreasonably large values. An extremely large EC_STRESS_COMPONENTS value would cause buildSnapshot to allocate a massive slice, likely causing OOM.

)

func main() {
driver.Main("Stress", benchmark)
}

func envInt(name string, fallback int) int {
v, ok := os.LookupEnv(name)
if !ok {
return fallback
Comment thread
dheerajodha marked this conversation as resolved.
}
n, err := strconv.Atoi(v)
if err != nil {
panic(fmt.Sprintf("invalid %s value %q: %v", name, v, err))
Comment thread
dheerajodha marked this conversation as resolved.
}
if n < 1 {
panic(fmt.Sprintf("%s must be >= 1, got %d", name, n))
}
return n
}

func setup() (string, suite.Closer) {
dir, err := untar.UnTar("data.tar.gz")
if err != nil {
panic(err)
}

closer, err := registry.Launch(path.Join(dir, "data/registry/data"))
if err != nil {
Comment thread
dheerajodha marked this conversation as resolved.
panic(err)
}

return dir, func() {
closer()
os.RemoveAll(dir)
}
}

type component struct {
Name string `json:"name"`

Check failure on line 82 in benchmark/stress/stress.go

View workflow job for this annotation

GitHub Actions / Lint

File is not properly formatted (gci)
ContainerImage string `json:"containerImage"`
Source *source `json:"source,omitempty"`
}

type source struct {
Git gitSource `json:"git"`
}

type gitSource struct {
URL string `json:"url"`
Revision string `json:"revision"`
}

type snapshot struct {
Components []component `json:"components"`

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[medium] stale-reference

The git source URL for golden-container uses the old organization name enterprise-contract (https://github.com/enterprise-contract/golden-container.git) while the rest of the codebase has migrated to https://github.com/conforma/golden-container. The git revision also differs from the simple benchmark, suggesting it may reference a commit in the old repo.

Suggested fix: Use https://github.com/conforma/golden-container to match the existing simple benchmark pattern, and verify the revision hash exists in the conforma fork.

}

func buildSnapshot(n int) string {
s := snapshot{Components: make([]component, n)}
for i := range s.Components {
s.Components[i] = component{
Name: fmt.Sprintf("golden-container-%d", i),
ContainerImage: "quay.io/redhat-user-workloads/rhtap-contract-tenant/golden-container/golden-container@sha256:166e38c156fa81d577a7ba7a948b68c79005a06e302779d1bebc7d31e8bea315",
Source: &source{
Git: gitSource{
URL: "https://github.com/enterprise-contract/golden-container.git",
Revision: "8327c1ce7472b017b9396fe26d5d5e1ed0eb61cc",
},
},
}
}

data, err := json.Marshal(s)
if err != nil {
panic(err)
}
return string(data)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[info] pattern-violation

The policy JSON string uses well-formed JSON (no trailing commas) while the simple benchmark has trailing commas. The stress benchmark is more correct, but the inconsistency is notable.

}

func benchmark() driver.Result {
dir, closer := setup()
defer closer()

components := envInt("EC_STRESS_COMPONENTS", defaultComponents)
workers := envInt("EC_STRESS_WORKERS", defaultWorkers)

return driver.Benchmark(run(dir, components, workers))
}

func ec(dir string, components, workers int) func() {
snap := buildSnapshot(components)

policy := fmt.Sprintf(`{
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZP/0htjhVt2y0ohjgtIIgICOtQtA\nnaYJRuLprwIv6FDhZ5yFjYUEtsmoNcW7rx2KM6FOXGsCX3BNc7qhHELT+g==\n-----END PUBLIC KEY-----",
"sources": [
{
"data": [
"git::file://%s/data/git/rhtap-ec-policy.git//data?ref=a524ee2f2f7774f6f360eb64c4cb24004de52aae",
"oci::quay.io/konflux-ci/tekton-catalog/data-acceptable-bundles@sha256:1e70b8f672388838f20a7d45e145e31e99dab06cefa1c5514d6ce41c8bbea1b0"
],
"policy": [
"oci::quay.io/enterprise-contract/ec-release-policy@sha256:64617f0c45689ef7152c5cfbd4cd5709a3126e4ab7482eb6acd994387fe2d4ba"
],
"config": {
"include": [
"@redhat"
]
}
}
]
}`, dir)

return func() {
if err := suite.Execute([]string{
"validate",
"image",
"--json-input",
snap,
"--policy",
policy,
"--ignore-rekor",
"--workers",
strconv.Itoa(workers),
"--effective-time",
"2024-12-10T00:00:00Z",
}); err != nil {
panic(err)
}
}
}

func run(dir string, components, workers int) func(n uint64) {
return func(n uint64) {
driver.Parallel(n, 1, ec(dir, components, workers))
}
}
Loading