ci: single Gitea Actions pipeline, uv-based image, scoped docker cleanup
Replace lint/test/docker workflows with ci.yml (gitleaks, lint, test-unit, test-integration, test-mcp, build-and-push, docs-check, security). Rebuild the Dockerfile as a digest-pinned multi-stage uv build running as uid 1000, add .dockerignore, a hardened compose file and a gitleaks config. The integration harness now falls back to /etc/hostname and /proc/self to find its own container.
This commit is contained in:
1 parent
9e50859133
commit
1a039e32ab
16 files changed
+729
-404
No files matched your search
Executable
+51
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env bash
|
||||
# Remove the Docker resources that THIS job created, and nothing else.
|
||||
#
|
||||
# Usage: scripts/ci/cleanup_job_resources.sh [image-ref ...]
|
||||
#
|
||||
# The runner shares one Docker daemon with other jobs and other services, so
|
||||
# this script never prunes. It only removes:
|
||||
# * per-run networks named aegis-it-* that the job container is attached to
|
||||
# (the integration harness joins the job container to its own per-run
|
||||
# network only), plus the containers still attached to those networks;
|
||||
# * containers started from the exact image refs given as arguments;
|
||||
# * the exact image refs given as arguments.
|
||||
# Everything is best effort (a failing removal never fails the job).
|
||||
set -uo pipefail
|
||||
|
||||
job_ref=""
|
||||
if command -v uv > /dev/null 2>&1 && [ -f tests/integration/harness.py ]; then
|
||||
job_ref="$(uv run python -c \
|
||||
'from tests.integration.harness import job_container_ref; print(job_container_ref())' \
|
||||
2> /dev/null || true)"
|
||||
fi
|
||||
if [ -z "${job_ref}" ]; then
|
||||
job_ref="${HOSTNAME:-}"
|
||||
fi
|
||||
|
||||
if [ -n "${job_ref}" ] && docker container inspect "${job_ref}" > /dev/null 2>&1; then
|
||||
job_id="$(docker container inspect --format '{{.Id}}' "${job_ref}")"
|
||||
networks="$(docker container inspect \
|
||||
--format '{{range $name, $_ := .NetworkSettings.Networks}}{{$name}}{{"\n"}}{{end}}' \
|
||||
"${job_ref}" | grep -E '^aegis-it-[0-9a-f]+$' || true)"
|
||||
for net in ${networks}; do
|
||||
for cid in $(docker network inspect --format '{{range $id, $_ := .Containers}}{{$id}}{{"\n"}}{{end}}' "${net}" 2> /dev/null); do
|
||||
if [ "${cid}" != "${job_id}" ]; then
|
||||
docker rm -f -v "${cid}" > /dev/null 2>&1 || true
|
||||
fi
|
||||
done
|
||||
docker network disconnect -f "${net}" "${job_id}" > /dev/null 2>&1 || true
|
||||
docker network rm "${net}" > /dev/null 2>&1 || true
|
||||
echo "removed network ${net}"
|
||||
done
|
||||
fi
|
||||
|
||||
for image in "$@"; do
|
||||
for cid in $(docker ps -aq --filter "ancestor=${image}" 2> /dev/null); do
|
||||
docker rm -f -v "${cid}" > /dev/null 2>&1 || true
|
||||
done
|
||||
docker rmi "${image}" > /dev/null 2>&1 || true
|
||||
echo "removed image ${image}"
|
||||
done
|
||||
|
||||
exit 0
|
||||
Executable
+46
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env bash
|
||||
# Install a pinned gitleaks release into a directory, verifying its sha256.
|
||||
#
|
||||
# Usage: scripts/ci/install_gitleaks.sh <dest-dir>
|
||||
#
|
||||
# The binary ends up at <dest-dir>/gitleaks. To upgrade, bump GITLEAKS_VERSION
|
||||
# and both digests from the release's gitleaks_<version>_checksums.txt.
|
||||
set -euo pipefail
|
||||
|
||||
GITLEAKS_VERSION="8.30.1"
|
||||
SHA256_X64="551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb"
|
||||
SHA256_ARM64="e4a487ee7ccd7d3a7f7ec08657610aa3606637dab924210b3aee62570fb4b080"
|
||||
|
||||
dest="${1:?usage: install_gitleaks.sh <dest-dir>}"
|
||||
|
||||
case "$(uname -m)" in
|
||||
x86_64 | amd64)
|
||||
arch="x64"
|
||||
expected="${SHA256_X64}"
|
||||
;;
|
||||
aarch64 | arm64)
|
||||
arch="arm64"
|
||||
expected="${SHA256_ARM64}"
|
||||
;;
|
||||
*)
|
||||
echo "unsupported architecture: $(uname -m)" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
archive="gitleaks_${GITLEAKS_VERSION}_linux_${arch}.tar.gz"
|
||||
url="https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/${archive}"
|
||||
|
||||
work="$(mktemp -d)"
|
||||
trap 'rm -rf "${work}"' EXIT
|
||||
|
||||
curl --fail --silent --show-error --location --retry 3 --output "${work}/${archive}" "${url}"
|
||||
echo "${expected} ${work}/${archive}" | sha256sum --check --status || {
|
||||
echo "sha256 mismatch for ${archive}" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
mkdir -p "${dest}"
|
||||
tar -xzf "${work}/${archive}" -C "${dest}" gitleaks
|
||||
chmod 0755 "${dest}/gitleaks"
|
||||
"${dest}/gitleaks" version
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
# Audit the locked dependency set with pip-audit.
|
||||
#
|
||||
# Ignored advisories (documented waivers, see docs/security.md) are read from
|
||||
# security/pip-audit-ignore.txt: one advisory id per line, '#' starts a comment.
|
||||
set -euo pipefail
|
||||
|
||||
ignore_file="security/pip-audit-ignore.txt"
|
||||
req="$(mktemp)"
|
||||
trap 'rm -f "${req}"' EXIT
|
||||
|
||||
uv export --locked --no-hashes --no-emit-project --format requirements-txt > "${req}"
|
||||
|
||||
args=(-r "${req}" --strict --no-deps --disable-pip)
|
||||
if [ -f "${ignore_file}" ]; then
|
||||
while IFS= read -r line; do
|
||||
id="${line%%#*}"
|
||||
id="$(echo "${id}" | tr -d '[:space:]')"
|
||||
if [ -n "${id}" ]; then
|
||||
args+=(--ignore-vuln "${id}")
|
||||
fi
|
||||
done < "${ignore_file}"
|
||||
fi
|
||||
|
||||
uv run pip-audit "${args[@]}"
|
||||
Reference in new issue
Block a user