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
4 changes: 4 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ RUN .venv/bin/pip install --no-cache-dir .

FROM python:3.12-slim-bookworm

RUN apt-get update \
&& apt-get install --no-install-recommends -y git ca-certificates \
&& rm -rf /var/lib/apt/lists/*

COPY --from=builder /app/.venv /app/.venv

ENV PATH="/app/.venv/bin:$PATH"
Expand Down
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: help install install-dev langgraph-dev test test-unit test-integration test-cov test-ci lint lint-fix format format-check clean build docker-build
.PHONY: help install install-dev langgraph-dev test test-unit test-integration test-cov test-ci lint lint-fix format format-check clean build docker-build docker-smoke

# Prefer uv if available, else use pip (set when Makefile is parsed)
UV := $(shell command -v uv 2>/dev/null)
Expand All @@ -25,6 +25,7 @@ help:
@echo " make clean - Remove build artifacts and cache files"
@echo " make build - Build the package"
@echo " make docker-build - Build the Docker image"
@echo " make docker-smoke - Build and smoke test the Docker image"

install:
@if [ -n "$(UV)" ]; then uv sync; else pip install -e .; fi
Expand Down Expand Up @@ -99,3 +100,6 @@ build: clean
docker-build:
docker build -t skillspector .

# Build and smoke test the Docker image
docker-smoke: docker-build
tests/docker/smoke.sh
60 changes: 60 additions & 0 deletions tests/docker/smoke.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/bin/sh
set -eu

IMAGE="${SKILLSPECTOR_DOCKER_IMAGE:-skillspector}"
REPO_DIR="${SKILLSPECTOR_REPO_DIR:-$(pwd)}"
LOCAL_REPORT="${SKILLSPECTOR_DOCKER_LOCAL_REPORT:-.skillspector-docker-smoke.json}"
GITHUB_REPORT="${SKILLSPECTOR_DOCKER_GITHUB_REPORT:-.skillspector-docker-github-smoke.json}"
GITHUB_URL="${SKILLSPECTOR_DOCKER_GITHUB_URL:-https://github.com/octocat/Hello-World}"
GITHUB_EXPECTED_COMPONENT="${SKILLSPECTOR_DOCKER_GITHUB_EXPECTED_COMPONENT:-README}"

run() {
printf "\n>> %s\n" "$*"
"$@"
}

validate_json_report() {
report_path="$1"

test -s "${REPO_DIR}/${report_path}"
run docker run --rm --entrypoint python -v "${REPO_DIR}:/scan" "${IMAGE}" \
-m json.tool "/scan/${report_path}" >/dev/null
}

assert_report_contains_component() {
report_path="$1"
expected_component="$2"

run docker run --rm --entrypoint python -v "${REPO_DIR}:/scan" "${IMAGE}" \
-c 'import json, sys; data = json.load(open("/scan/" + sys.argv[1])); expected = sys.argv[2]; assert any(c.get("path") == expected for c in data.get("components", [])), f"missing component: {expected}"' \
"${report_path}" "${expected_component}"
}

scan_github_url() {
printf "\n>> docker run --rm -v %s:/scan %s scan %s --no-llm --format json --output /scan/%s\n" \
"${REPO_DIR}" "${IMAGE}" "${GITHUB_URL}" "${GITHUB_REPORT}"

set +e
docker run --rm -v "${REPO_DIR}:/scan" "${IMAGE}" scan "${GITHUB_URL}" \
--no-llm --format json --output "/scan/${GITHUB_REPORT}"
github_scan_status="$?"
set -e

if [ "${github_scan_status}" -ne 0 ] && [ "${github_scan_status}" -ne 1 ]; then
echo "GitHub URL scan failed with exit code ${github_scan_status}"
exit "${github_scan_status}"
fi

validate_json_report "${GITHUB_REPORT}"
assert_report_contains_component "${GITHUB_REPORT}" "${GITHUB_EXPECTED_COMPONENT}"
echo "GitHub URL scan completed with accepted exit code ${github_scan_status}"
}

run docker run --rm "${IMAGE}" --version
run docker run --rm --entrypoint git "${IMAGE}" --version

run docker run --rm -v "${REPO_DIR}:/scan" "${IMAGE}" scan tests/fixtures/safe_skill \
--no-llm --format json --output "/scan/${LOCAL_REPORT}"
validate_json_report "${LOCAL_REPORT}"

scan_github_url