up
This commit is contained in:
29
scripts/cli/chaos-smoke.sh
Normal file
29
scripts/cli/chaos-smoke.sh
Normal file
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# DEVOPS-CLI-43-002: chaos smoke for Task Pack commands
|
||||
|
||||
CLI=${CLI:-"dotnet run --project src/Cli/StellaOps.Cli/StellaOps.Cli.csproj --no-build --"}
|
||||
RESULTS="out/cli-chaos"
|
||||
mkdir -p "$RESULTS"
|
||||
|
||||
PACK="${PACK:-tests/fixtures/task-packs/sample-pack.yaml}"
|
||||
RANDOM_FAIL=${RANDOM_FAIL:-true}
|
||||
SEALED=${SEALED:-false}
|
||||
|
||||
echo "[chaos] running pack=$PACK random_fail=$RANDOM_FAIL sealed=$SEALED"
|
||||
|
||||
set +e
|
||||
$CLI task-runner run --pack "$PACK" ${SEALED:+--sealed} ${RANDOM_FAIL:+--chaos-random-fail} >"$RESULTS/run.log" 2>&1
|
||||
status=$?
|
||||
set -e
|
||||
|
||||
echo "exit_code=$status" > "$RESULTS/metadata.txt"
|
||||
|
||||
if [[ $status -ne 0 && "$RANDOM_FAIL" == "true" ]]; then
|
||||
echo "[chaos] attempting resume after failure"
|
||||
$CLI task-runner resume --pack "$PACK" >>"$RESULTS/run.log" 2>&1 || true
|
||||
fi
|
||||
|
||||
tar -C "$RESULTS" -czf "$RESULTS/evidence.tgz" .
|
||||
echo "[chaos] evidence archived at $RESULTS/evidence.tgz"
|
||||
36
scripts/cli/parity-diff.sh
Normal file
36
scripts/cli/parity-diff.sh
Normal file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# DEVOPS-CLI-43-003: parity diff for CLI golden outputs
|
||||
|
||||
EXPECTED_DIR=${EXPECTED_DIR:-"tests/goldens"}
|
||||
ACTUAL_DIR=${ACTUAL_DIR:-"out/cli-goldens"}
|
||||
CLI=${CLI:-"dotnet run --project src/Cli/StellaOps.Cli/StellaOps.Cli.csproj --no-build --"}
|
||||
|
||||
mkdir -p "$ACTUAL_DIR"
|
||||
|
||||
run_case() {
|
||||
local name=$1
|
||||
local args=$2
|
||||
local outfile="${ACTUAL_DIR}/${name}.txt"
|
||||
echo "[parity] running ${name}: ${args}"
|
||||
$CLI $args > "$outfile"
|
||||
}
|
||||
|
||||
run_case "help" "--help"
|
||||
run_case "scan-help" "scan --help"
|
||||
|
||||
diffs=0
|
||||
for expected in $(find "$EXPECTED_DIR" -name '*.txt'); do
|
||||
rel=${expected#$EXPECTED_DIR/}
|
||||
actual="${ACTUAL_DIR}/${rel}"
|
||||
if ! diff -u "$expected" "$actual" > "${ACTUAL_DIR}/${rel}.diff" 2>/dev/null; then
|
||||
echo "[parity] diff for $rel"
|
||||
diffs=$((diffs+1))
|
||||
else
|
||||
rm -f "${ACTUAL_DIR}/${rel}.diff"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "[parity] total diffs: $diffs"
|
||||
echo "$diffs" > "${ACTUAL_DIR}/summary.txt"
|
||||
48
scripts/devportal/build-devportal.sh
Normal file
48
scripts/devportal/build-devportal.sh
Normal file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# DEVOPS-DEVPORT-63-001 / 64-001: devportal build + offline bundle
|
||||
|
||||
ROOT="$(git rev-parse --show-toplevel)"
|
||||
pushd "$ROOT" >/dev/null
|
||||
|
||||
OUT_ROOT="out/devportal"
|
||||
RUN_ID="$(date -u +%Y%m%dT%H%M%SZ)"
|
||||
RUN_DIR="${OUT_ROOT}/${RUN_ID}"
|
||||
mkdir -p "$RUN_DIR"
|
||||
|
||||
export NODE_ENV=production
|
||||
export PNPM_HOME="${ROOT}/.pnpm"
|
||||
export PATH="$PNPM_HOME:$PATH"
|
||||
|
||||
if ! command -v pnpm >/dev/null 2>&1; then
|
||||
corepack enable pnpm >/dev/null
|
||||
fi
|
||||
|
||||
echo "[devportal] installing deps with pnpm"
|
||||
pnpm install --frozen-lockfile --prefer-offline
|
||||
|
||||
echo "[devportal] lint/typecheck/unit"
|
||||
pnpm run lint
|
||||
pnpm run test -- --watch=false
|
||||
|
||||
echo "[devportal] lighthouse perf budget (headless)"
|
||||
pnpm run perf:ci || true
|
||||
|
||||
echo "[devportal] build"
|
||||
pnpm run build
|
||||
|
||||
echo "[devportal] copying artifacts"
|
||||
cp -r dist "${RUN_DIR}/dist"
|
||||
|
||||
echo "[devportal] checksums"
|
||||
(
|
||||
cd "$RUN_DIR"
|
||||
find dist -type f -print0 | xargs -0 sha256sum > SHA256SUMS
|
||||
)
|
||||
|
||||
tar -C "$RUN_DIR" -czf "${RUN_DIR}.tgz" dist SHA256SUMS
|
||||
echo "$RUN_DIR.tgz" > "${OUT_ROOT}/latest.txt"
|
||||
echo "[devportal] bundle created at ${RUN_DIR}.tgz"
|
||||
|
||||
popd >/dev/null
|
||||
22
scripts/export/oci-verify.sh
Normal file
22
scripts/export/oci-verify.sh
Normal file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Verify OCI distribution path works (push/pull loop).
|
||||
|
||||
IMAGE=${IMAGE:-"ghcr.io/stella-ops/exporter:edge"}
|
||||
TMP="out/export-oci"
|
||||
mkdir -p "$TMP"
|
||||
|
||||
echo "[export-oci] pulling $IMAGE"
|
||||
docker pull "$IMAGE"
|
||||
|
||||
echo "[export-oci] retagging and pushing to local cache"
|
||||
LOCAL="localhost:5001/exporter:test"
|
||||
docker tag "$IMAGE" "$LOCAL"
|
||||
|
||||
docker push "$LOCAL" || echo "[export-oci] push skipped (no local registry?)"
|
||||
|
||||
echo "[export-oci] pulling back for verification"
|
||||
docker pull "$LOCAL" || true
|
||||
|
||||
echo "[export-oci] done"
|
||||
24
scripts/export/trivy-compat.sh
Normal file
24
scripts/export/trivy-compat.sh
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# DEVOPS-EXPORT-36-001: Trivy compatibility & signing checks
|
||||
|
||||
IMAGE=${IMAGE:-"ghcr.io/stella-ops/exporter:edge"}
|
||||
OUT="out/export-compat"
|
||||
mkdir -p "$OUT"
|
||||
|
||||
echo "[export-compat] pulling image $IMAGE"
|
||||
docker pull "$IMAGE"
|
||||
|
||||
echo "[export-compat] running trivy image --severity HIGH,CRITICAL"
|
||||
trivy image --severity HIGH,CRITICAL --quiet "$IMAGE" > "$OUT/trivy.txt" || true
|
||||
|
||||
echo "[export-compat] verifying cosign signature if present"
|
||||
if command -v cosign >/dev/null 2>&1; then
|
||||
cosign verify "$IMAGE" > "$OUT/cosign.txt" || true
|
||||
fi
|
||||
|
||||
echo "[export-compat] trivy module db import smoke"
|
||||
trivy module db import --file "$OUT/trivy-module.db" 2>/dev/null || true
|
||||
|
||||
echo "[export-compat] done; outputs in $OUT"
|
||||
47
scripts/graph/load-test.sh
Normal file
47
scripts/graph/load-test.sh
Normal file
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# DEVOPS-GRAPH-24-001: load test graph index/adjacency APIs
|
||||
|
||||
TARGET=${TARGET:-"http://localhost:5000"}
|
||||
OUT="out/graph-load"
|
||||
mkdir -p "$OUT"
|
||||
|
||||
USERS=${USERS:-8}
|
||||
DURATION=${DURATION:-60}
|
||||
RATE=${RATE:-200}
|
||||
|
||||
cat > "${OUT}/k6-graph.js" <<'EOF'
|
||||
import http from 'k6/http';
|
||||
import { sleep } from 'k6';
|
||||
|
||||
export const options = {
|
||||
vus: __USERS__,
|
||||
duration: '__DURATION__s',
|
||||
thresholds: {
|
||||
http_req_duration: ['p(95)<500'],
|
||||
http_req_failed: ['rate<0.01'],
|
||||
},
|
||||
};
|
||||
|
||||
const targets = [
|
||||
'/graph/api/index',
|
||||
'/graph/api/adjacency?limit=100',
|
||||
'/graph/api/search?q=log4j',
|
||||
];
|
||||
|
||||
export default function () {
|
||||
const host = __TARGET__;
|
||||
targets.forEach(path => http.get(`${host}${path}`));
|
||||
sleep(1);
|
||||
}
|
||||
EOF
|
||||
|
||||
sed -i "s/__USERS__/${USERS}/g" "${OUT}/k6-graph.js"
|
||||
sed -i "s/__DURATION__/${DURATION}/g" "${OUT}/k6-graph.js"
|
||||
sed -i "s@__TARGET__@\"${TARGET}\"@g" "${OUT}/k6-graph.js"
|
||||
|
||||
echo "[graph-load] running k6..."
|
||||
k6 run "${OUT}/k6-graph.js" --summary-export "${OUT}/summary.json" --http-debug="off"
|
||||
|
||||
echo "[graph-load] summary written to ${OUT}/summary.json"
|
||||
21
scripts/graph/simulation-smoke.sh
Normal file
21
scripts/graph/simulation-smoke.sh
Normal file
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# DEVOPS-GRAPH-24-003: simulation endpoint smoke
|
||||
|
||||
TARGET=${TARGET:-"http://localhost:5000"}
|
||||
OUT="out/graph-sim"
|
||||
mkdir -p "$OUT"
|
||||
|
||||
echo "[graph-sim] hitting simulation endpoints"
|
||||
|
||||
curl -sSf "${TARGET}/graph/api/simulation/ping" > "${OUT}/ping.json"
|
||||
curl -sSf "${TARGET}/graph/api/simulation/run?limit=5" > "${OUT}/run.json"
|
||||
|
||||
cat > "${OUT}/summary.txt" <<EOF
|
||||
ping: $(jq -r '.status' "${OUT}/ping.json" 2>/dev/null || echo "unknown")
|
||||
run_len: $(jq '. | length' "${OUT}/run.json" 2>/dev/null || echo "0")
|
||||
EOF
|
||||
|
||||
echo "[graph-sim] completed; summary:"
|
||||
cat "${OUT}/summary.txt"
|
||||
30
scripts/graph/ui-perf.ts
Normal file
30
scripts/graph/ui-perf.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { chromium } from 'playwright';
|
||||
import fs from 'fs';
|
||||
|
||||
const BASE_URL = process.env.GRAPH_UI_BASE ?? 'http://localhost:4200';
|
||||
const OUT = process.env.OUT ?? 'out/graph-ui-perf';
|
||||
const BUDGET_MS = Number(process.env.GRAPH_UI_BUDGET_MS ?? '3000');
|
||||
|
||||
(async () => {
|
||||
fs.mkdirSync(OUT, { recursive: true });
|
||||
const browser = await chromium.launch({ headless: true });
|
||||
const page = await browser.newPage();
|
||||
|
||||
const start = Date.now();
|
||||
await page.goto(`${BASE_URL}/graph`, { waitUntil: 'networkidle' });
|
||||
await page.click('text=Explore'); // assumes nav element
|
||||
await page.waitForSelector('canvas');
|
||||
const duration = Date.now() - start;
|
||||
|
||||
const metrics = await page.evaluate(() => JSON.stringify(window.performance.timing));
|
||||
fs.writeFileSync(`${OUT}/timing.json`, metrics);
|
||||
fs.writeFileSync(`${OUT}/duration.txt`, `${duration}`);
|
||||
|
||||
if (duration > BUDGET_MS) {
|
||||
console.error(`[graph-ui] perf budget exceeded: ${duration}ms > ${BUDGET_MS}ms`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
await browser.close();
|
||||
console.log(`[graph-ui] load duration ${duration}ms (budget ${BUDGET_MS}ms)`);
|
||||
})();
|
||||
46
scripts/scanner/package-analyzer.sh
Normal file
46
scripts/scanner/package-analyzer.sh
Normal file
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Package a scanner analyzer plugin with checksum and SBOM.
|
||||
# Usage: package-analyzer.sh <project-path> <name>
|
||||
|
||||
if [[ $# -lt 2 ]]; then
|
||||
echo "Usage: $0 <project-path> <name>" >&2
|
||||
exit 64
|
||||
fi
|
||||
|
||||
PROJECT=$1
|
||||
NAME=$2
|
||||
CONFIG=${CONFIG:-Release}
|
||||
RID=${RID:-linux-x64}
|
||||
OUT_ROOT="out/scanner-analyzers/${NAME}"
|
||||
PUBLISH_DIR="${OUT_ROOT}/publish"
|
||||
mkdir -p "$PUBLISH_DIR"
|
||||
|
||||
if ! command -v dotnet >/dev/null 2>&1; then
|
||||
echo "[analyzer] dotnet CLI not found" >&2
|
||||
exit 69
|
||||
fi
|
||||
|
||||
echo "[analyzer] publishing ${NAME} (${PROJECT}) for ${RID}"
|
||||
dotnet publish "$PROJECT" -c "$CONFIG" -r "$RID" --self-contained true -p:PublishSingleFile=true -p:PublishTrimmed=false -o "$PUBLISH_DIR" >/dev/null
|
||||
|
||||
ARCHIVE="${OUT_ROOT}/${NAME}-${RID}.tar.gz"
|
||||
tar -C "$PUBLISH_DIR" -czf "$ARCHIVE" .
|
||||
sha256sum "$ARCHIVE" > "${ARCHIVE}.sha256"
|
||||
|
||||
if command -v syft >/dev/null 2>&1; then
|
||||
syft "dir:${PUBLISH_DIR}" -o json > "${ARCHIVE}.sbom.json"
|
||||
fi
|
||||
|
||||
cat > "${OUT_ROOT}/manifest.json" <<EOF
|
||||
{
|
||||
"name": "${NAME}",
|
||||
"project": "${PROJECT}",
|
||||
"rid": "${RID}",
|
||||
"generated_at": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
|
||||
"archive": "$(basename "$ARCHIVE")"
|
||||
}
|
||||
EOF
|
||||
|
||||
echo "[analyzer] packaged ${NAME} at ${ARCHIVE}"
|
||||
Reference in New Issue
Block a user