Adding the sha based version pinnig
This commit is contained in:
1 parent
cf3e12e9d2
commit
34d8b5a299
11 files changed
+2266
-55
No files matched your search
@@ -18,14 +18,13 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12'
|
||||
python-version: '3.14'
|
||||
cache: pip
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
pip install coverage
|
||||
pip install --require-hashes -r requirements.dev.txt
|
||||
|
||||
- name: Ruff lint
|
||||
run: ruff check .
|
||||
@@ -43,6 +42,13 @@ jobs:
|
||||
contents: read
|
||||
packages: write
|
||||
id-token: write
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- image_tag: ghcr.io/k2patel/apcupsd-client:latest
|
||||
melange_config: melange.yaml
|
||||
- image_tag: ghcr.io/k2patel/apcupsd-client-dev:latest
|
||||
melange_config: melange.dev.yaml
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
@@ -55,7 +61,7 @@ jobs:
|
||||
|
||||
- name: Build package with melange
|
||||
run: |
|
||||
melange build melange.yaml \
|
||||
melange build ${{ matrix.melange_config }} \
|
||||
--signing-key melange.rsa \
|
||||
--arch x86_64,aarch64
|
||||
|
||||
@@ -71,6 +77,5 @@ jobs:
|
||||
with:
|
||||
config: apko.yaml
|
||||
archs: x86_64,aarch64
|
||||
tag: ghcr.io/k2patel/apcupsd-client:latest
|
||||
tag: ${{ matrix.image_tag }}
|
||||
keyring-append: melange.rsa.pub
|
||||
|
||||
+10
-6
@@ -1,7 +1,10 @@
|
||||
# syntax=docker/dockerfile:1.6
|
||||
# NOTE: The primary build method is now melange + apko (see melange.yaml / apko.yaml).
|
||||
# This Dockerfile is kept for local dev and Docker Compose backward compatibility.
|
||||
FROM python:3.12.7-slim AS builder
|
||||
ARG PYTHON_IMAGE=python:3.14.5-slim@sha256:c845af9399020c7e562969a13689e929074a10fd057acd1b1fad06a2fb068e97
|
||||
ARG REQUIREMENTS_FILE=requirements.txt
|
||||
FROM ${PYTHON_IMAGE} AS builder
|
||||
ARG REQUIREMENTS_FILE
|
||||
|
||||
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
@@ -13,11 +16,12 @@ RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends build-essential gcc \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY requirements.txt ./
|
||||
RUN pip install --upgrade pip && pip wheel --wheel-dir /wheels -r requirements.txt
|
||||
COPY ${REQUIREMENTS_FILE} requirements.txt
|
||||
RUN pip install --upgrade pip && pip wheel --require-hashes --wheel-dir /wheels -r requirements.txt
|
||||
|
||||
|
||||
FROM python:3.12.7-slim AS runtime
|
||||
FROM ${PYTHON_IMAGE} AS runtime
|
||||
ARG REQUIREMENTS_FILE
|
||||
|
||||
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
@@ -33,8 +37,8 @@ RUN apt-get update \
|
||||
&& useradd --system --uid 10001 --gid 10001 --home /app --shell /usr/sbin/nologin appuser
|
||||
|
||||
COPY --from=builder /wheels /wheels
|
||||
COPY requirements.txt ./
|
||||
RUN pip install --no-index --find-links=/wheels -r requirements.txt \
|
||||
COPY ${REQUIREMENTS_FILE} requirements.txt
|
||||
RUN pip install --no-index --find-links=/wheels --require-hashes -r requirements.txt \
|
||||
&& rm -rf /wheels
|
||||
|
||||
COPY app ./app
|
||||
|
||||
@@ -23,7 +23,7 @@ A production-ready FastAPI + Redis dashboard for monitoring multiple APC UPS dev
|
||||
- SSRF host validation (rejects loopback/link-local; private IPs gated by `ALLOW_PRIVATE_IPS`)
|
||||
- SMTP password **only** from env — never persisted to Redis
|
||||
- Subprocess timeout on `apcaccess` (10s), rate-limiting on auth/config, security headers + CSP
|
||||
- Non-root container (UID 10001), pinned `python:3.12.7-slim` multi-stage build
|
||||
- Non-root container (UID 10001), digest-pinned `python:3.14.5-slim` multi-stage build
|
||||
- `/healthz`, `/readyz`, `/metrics` (Prometheus), JSON structured logs with request-ID correlation
|
||||
- GitHub Actions pipeline runs ruff + pytest before building/publishing the image
|
||||
|
||||
@@ -82,9 +82,12 @@ Your remote APC UPS hosts must run `apcupsd` with the Network Information Server
|
||||
|
||||
## Development
|
||||
|
||||
Production Docker builds install `requirements.txt`; local development and CI use
|
||||
`requirements.dev.txt`.
|
||||
|
||||
```bash
|
||||
python3.12 -m venv .venv && . .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
python3.14 -m venv .venv && . .venv/bin/activate
|
||||
pip install -r requirements.dev.txt
|
||||
|
||||
# Run tests (uses fakeredis)
|
||||
pytest tests/
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package:
|
||||
name: apcupsd-client-build
|
||||
version: 1.0.0
|
||||
epoch: 0
|
||||
description: Build stage for apcupsd-client dev image (not installed directly)
|
||||
copyright:
|
||||
- license: MIT
|
||||
|
||||
environment:
|
||||
contents:
|
||||
repositories:
|
||||
- https://dl-cdn.alpinelinux.org/alpine/v3.21/main
|
||||
- https://dl-cdn.alpinelinux.org/alpine/v3.21/community
|
||||
packages:
|
||||
- alpine-baselayout
|
||||
- busybox
|
||||
- python3
|
||||
- py3-pip
|
||||
- py3-virtualenv
|
||||
|
||||
pipeline:
|
||||
- name: Create virtualenv and install dependencies
|
||||
runs: |
|
||||
set -ex
|
||||
mkdir -p "${{targets.destdir}}/app"
|
||||
python3 -m virtualenv "${{targets.destdir}}/app/.venv"
|
||||
"${{targets.destdir}}/app/.venv/bin/pip" install \
|
||||
--no-cache-dir \
|
||||
--only-binary :all: \
|
||||
--require-hashes \
|
||||
-r requirements.dev.txt
|
||||
|
||||
- name: Copy application source
|
||||
runs: |
|
||||
set -ex
|
||||
cp -r app/ "${{targets.destdir}}/app/app/"
|
||||
|
||||
- name: Fix virtualenv shebangs
|
||||
runs: |
|
||||
set -ex
|
||||
find "${{targets.destdir}}/app/.venv/bin" -type f -exec \
|
||||
sed -i "s|${{targets.destdir}}||g" {} +
|
||||
|
||||
- name: Strip build artifacts from virtualenv
|
||||
runs: |
|
||||
set -ex
|
||||
rm -rf "${{targets.destdir}}/app/.venv/bin/pip"*
|
||||
rm -rf "${{targets.destdir}}/app/.venv/bin/wheel"*
|
||||
rm -rf "${{targets.destdir}}/app/.venv/lib/python*/site-packages/pip"
|
||||
rm -rf "${{targets.destdir}}/app/.venv/lib/python*/site-packages/pip-*"
|
||||
rm -rf "${{targets.destdir}}/app/.venv/lib/python*/site-packages/setuptools"
|
||||
rm -rf "${{targets.destdir}}/app/.venv/lib/python*/site-packages/setuptools-*"
|
||||
rm -rf "${{targets.destdir}}/app/.venv/lib/python*/site-packages/wheel"
|
||||
rm -rf "${{targets.destdir}}/app/.venv/lib/python*/site-packages/wheel-*"
|
||||
find "${{targets.destdir}}/app/.venv" -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null || true
|
||||
find "${{targets.destdir}}/app/.venv" -name "*.pyc" -delete 2>/dev/null || true
|
||||
|
||||
subpackages:
|
||||
- name: apcupsd-client
|
||||
description: FastAPI + Redis UPS monitoring dashboard with dev dependencies
|
||||
options:
|
||||
no-depends: true
|
||||
dependencies:
|
||||
runtime:
|
||||
- python3
|
||||
pipeline:
|
||||
- runs: |
|
||||
set -ex
|
||||
mkdir -p "${{targets.subpkgdir}}"
|
||||
mv "${{targets.destdir}}/app" "${{targets.subpkgdir}}/app"
|
||||
+2
-1
@@ -27,7 +27,8 @@ pipeline:
|
||||
"${{targets.destdir}}/app/.venv/bin/pip" install \
|
||||
--no-cache-dir \
|
||||
--only-binary :all: \
|
||||
-r requirements.prod.txt
|
||||
--require-hashes \
|
||||
-r requirements.txt
|
||||
|
||||
- name: Copy application source
|
||||
runs: |
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@
|
||||
name = "apcupsd-client"
|
||||
version = "0.2.0"
|
||||
description = "FastAPI + Redis dashboard for monitoring multiple APC UPS devices via apcupsd NIS"
|
||||
requires-python = ">=3.12"
|
||||
requires-python = ">=3.14"
|
||||
readme = "README.md"
|
||||
license = { text = "MIT" }
|
||||
|
||||
@@ -17,7 +17,7 @@ filterwarnings = [
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 100
|
||||
target-version = "py312"
|
||||
target-version = "py314"
|
||||
extend-exclude = [".venv", "app/static"]
|
||||
|
||||
[tool.ruff.lint]
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
-r requirements.in
|
||||
|
||||
# Dev / test dependencies
|
||||
coverage
|
||||
pytest
|
||||
pytest-asyncio
|
||||
httpx
|
||||
fakeredis
|
||||
ruff
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,15 @@
|
||||
fastapi
|
||||
uvicorn[standard]
|
||||
pyyaml
|
||||
redis
|
||||
pydantic
|
||||
pydantic-settings
|
||||
jinja2
|
||||
python-multipart
|
||||
orjson
|
||||
passlib[argon2]
|
||||
itsdangerous
|
||||
slowapi
|
||||
python-json-logger
|
||||
tenacity
|
||||
prometheus-client
|
||||
@@ -1,15 +0,0 @@
|
||||
fastapi==0.115.0
|
||||
uvicorn[standard]==0.30.6
|
||||
pyyaml==6.0.2
|
||||
redis==5.0.7
|
||||
pydantic==2.9.2
|
||||
pydantic-settings==2.5.2
|
||||
jinja2==3.1.4
|
||||
python-multipart==0.0.9
|
||||
orjson==3.10.7
|
||||
passlib[argon2]==1.7.4
|
||||
itsdangerous==2.2.0
|
||||
slowapi==0.1.9
|
||||
python-json-logger==2.0.7
|
||||
tenacity==9.0.0
|
||||
prometheus-client==0.21.0
|
||||
+980
-22
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user