Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
459198c
feat: add notification destinations
kylejschultz Jul 7, 2026
7eaa440
feat: add Slack webhook setup help
kylejschultz Jul 7, 2026
a1a6eb6
feat: streamline notification destination setup
kylejschultz Jul 8, 2026
065d35d
fix: improve destination editor testing
kylejschultz Jul 8, 2026
4a1e01e
Polish notification settings layout
kylejschultz Jul 9, 2026
dbebce7
Polish notification destination type icons
kylejschultz Jul 10, 2026
ea9b443
Use standard icons for notification destinations
kylejschultz Jul 17, 2026
9365c88
chore(deps): bump actions/setup-node from 6.4.0 to 7.0.0 (#148)
dependabot[bot] Jul 17, 2026
3e8f518
chore(deps-dev): bump @vitejs/plugin-react in /frontend (#147)
dependabot[bot] Jul 17, 2026
e1f9552
chore(deps): bump react-router-dom from 7.15.1 to 7.18.1 in /frontend…
dependabot[bot] Jul 17, 2026
b573d67
chore: apply remaining dependency updates
kylejschultz Jul 17, 2026
06a2ddd
ci: add release-please release flow
kylejschultz Jul 22, 2026
c979570
ci: pin release workflow actions
kylejschultz Jul 22, 2026
5558fe3
feat: simplify container alert exceptions
kylejschultz Jul 22, 2026
d46b51a
Merge remote-tracking branch 'origin/main' into dev
kylejschultz Jul 23, 2026
d61f50d
fix: limit release announcement notes to current version
kylejschultz Jul 23, 2026
42619dc
feat: add v2 redesign shell preview
kylejschultz Jul 30, 2026
cf7e468
fix: clear security scan dependency findings
kylejschultz Jul 30, 2026
d0694db
fix: disable trivy scan cache
kylejschultz Jul 30, 2026
88a6cb2
fix: remove pip from runtime image
kylejschultz Jul 30, 2026
79bf34d
feat: clarify dev build identity
kylejschultz Jul 30, 2026
abd798b
feat: add v2 containers inventory
kylejschultz Jul 30, 2026
19750e2
Tighten containers inventory layout
kylejschultz Jul 30, 2026
0a9fcbc
Clarify container resource rows
kylejschultz Jul 30, 2026
f386b6b
Refine containers row interactions
kylejschultz Jul 30, 2026
06517d0
fix: remove duplicate container uptime detail
kylejschultz Jul 30, 2026
5e9dd1b
Add collapsible sidebar
kylejschultz Jul 30, 2026
b6a06b0
Fade stopped container rows
kylejschultz Jul 30, 2026
f4c4153
Polish containers mobile summary
kylejschultz Jul 30, 2026
9fcbf05
Simplify containers table summary
kylejschultz Jul 30, 2026
4535419
Polish expanded container metadata wrapping
kylejschultz Jul 30, 2026
6e787a2
Keep expanded container details dense
kylejschultz Jul 30, 2026
3bacb70
Restructure container detail inspector
kylejschultz Jul 30, 2026
5633865
Polish container detail layout density
kylejschultz Jul 30, 2026
f65308f
feat: add container operational detail metadata
kylejschultz Jul 30, 2026
8c6dd2b
fix: keep network stat within detail card
kylejschultz Jul 31, 2026
b28924d
fix: show container name in sticky header
kylejschultz Jul 31, 2026
8d85e5f
Add collapsible container overview
kylejschultz Jul 31, 2026
3dba800
Improve container overview interactions
kylejschultz Jul 31, 2026
28f40c3
Add services setup page
kylejschultz Jul 31, 2026
e9e37a3
ci: publish pr preview images (#161)
kylejschultz Aug 1, 2026
6e01208
chore: Refresh development dependencies (#172)
kylejschultz Aug 14, 2026
943dcca
fix: Patch high-severity dependency findings (#170) (#174)
kylejschultz Aug 14, 2026
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
2 changes: 1 addition & 1 deletion .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Deploy to Cloudflare Pages
env:
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/publish-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Log in to GHCR
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand All @@ -40,6 +40,7 @@ jobs:
run: |
docker build --platform ${{ matrix.platform }} \
--build-arg BUILD_CHANNEL=dev \
--build-arg BUILD_LABEL="v2 dev" \
--build-arg GIT_SHA=${{ steps.sha.outputs.short }} \
-t ghcr.io/kylejschultz/nestview:dev-${{ steps.sha.outputs.short }}-${{ matrix.suffix }} \
-f Dockerfile \
Expand All @@ -52,7 +53,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Log in to GHCR
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
Expand Down
89 changes: 89 additions & 0 deletions .github/workflows/publish-pr-preview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
name: Publish PR Preview

on:
pull_request:
branches: [dev]
types: [opened, synchronize, reopened]

permissions:
contents: read
packages: write

concurrency:
group: publish-pr-preview-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
build:
if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
runs-on: ${{ matrix.runner }}
strategy:
matrix:
include:
- platform: linux/amd64
runner: ubuntu-24.04
suffix: amd64
- platform: linux/arm64
runner: ubuntu-24.04-arm
suffix: arm64

steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Log in to GHCR
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set preview tags
id: preview
run: |
echo "short=$(echo ${{ github.event.pull_request.head.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT
echo "number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT

- name: Build and push
run: |
docker build --platform ${{ matrix.platform }} \
--build-arg BUILD_CHANNEL=pr \
--build-arg BUILD_LABEL="PR #${{ steps.preview.outputs.number }}" \
--build-arg GIT_SHA=${{ steps.preview.outputs.short }} \
-t ghcr.io/kylejschultz/nestview:pr-${{ steps.preview.outputs.number }}-${{ steps.preview.outputs.short }}-${{ matrix.suffix }} \
-f Dockerfile \
.
docker push ghcr.io/kylejschultz/nestview:pr-${{ steps.preview.outputs.number }}-${{ steps.preview.outputs.short }}-${{ matrix.suffix }}

merge:
if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
runs-on: ubuntu-24.04
needs: [build]

steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Log in to GHCR
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set preview tags
id: preview
run: |
echo "short=$(echo ${{ github.event.pull_request.head.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT
echo "number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0

- name: Merge manifest
run: |
docker buildx imagetools create \
-t ghcr.io/kylejschultz/nestview:pr-${{ steps.preview.outputs.number }} \
-t ghcr.io/kylejschultz/nestview:pr-${{ steps.preview.outputs.number }}-${{ steps.preview.outputs.short }} \
ghcr.io/kylejschultz/nestview:pr-${{ steps.preview.outputs.number }}-${{ steps.preview.outputs.short }}-amd64 \
ghcr.io/kylejschultz/nestview:pr-${{ steps.preview.outputs.number }}-${{ steps.preview.outputs.short }}-arm64
10 changes: 5 additions & 5 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event_name == 'release' && github.event.release.tag_name || inputs.ref }}

- name: Log in to GHCR
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand Down Expand Up @@ -70,7 +70,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event_name == 'release' && github.event.release.tag_name || inputs.ref }}

Expand Down Expand Up @@ -108,7 +108,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event_name == 'release' && github.event.release.tag_name || inputs.ref }}

Expand Down Expand Up @@ -144,7 +144,7 @@ jobs:
changelog = changelog_file.read()

section_match = re.search(
rf"^## \[{re.escape(version)}\].*?\n(.*?)(?=\n---\n## |\Z)",
rf"^## \[{re.escape(version)}\].*?\n(.*?)(?=\n(?:---\n)?## \[|\Z)",
changelog,
re.MULTILINE | re.DOTALL,
)
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
fi

- name: Create or update release PR
uses: googleapis/release-please-action@5c625bfb5d1ff62eadeeb3772007f7f66fdcf071 # v4
uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0
with:
token: ${{ secrets.RELEASE_PLEASE_TOKEN }}
config-file: release-please-config.json
Expand Down
9 changes: 5 additions & 4 deletions .github/workflows/security-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.14"
cache: pip
Expand All @@ -40,7 +40,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
Expand All @@ -63,7 +63,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Build image
run: |
Expand All @@ -79,6 +79,7 @@ jobs:
image-ref: nestview:security-scan
format: table
ignore-unfixed: true
cache: false
severity: HIGH,CRITICAL
vuln-type: os,library
exit-code: "1"
8 changes: 4 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.14"
cache: pip
Expand All @@ -37,7 +37,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
Expand All @@ -60,7 +60,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Build image
run: |
Expand Down
5 changes: 5 additions & 0 deletions .trivyignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# False positives in the embedded SBOM of python:3.14-slim. The runtime image
# does not contain either package; verified against the upstream base image on
# 2026-08-13. Reassess after the upstream SBOM refreshes.
GHSA-6v7p-g79w-8964 exp:2026-09-13
CVE-2025-47273 exp:2026-09-13
14 changes: 9 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,20 @@ FROM python:3.14-slim
ARG BUILD_CHANNEL
ENV BUILD_CHANNEL=${BUILD_CHANNEL}

ARG GIT_SHA=unknown
ENV BUILD_SHA=${GIT_SHA}

RUN pip install --no-cache-dir --upgrade pip
ARG BUILD_LABEL
ENV BUILD_LABEL=${BUILD_LABEL}

WORKDIR /app

# Backend dependencies
COPY backend/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
RUN pip install --no-cache-dir --upgrade "setuptools>=78.1.1" \
&& pip install --no-cache-dir -r requirements.txt \
&& python -m pip uninstall -y pip \
&& find /usr/local/lib/python3.14/site-packages -maxdepth 1 -name "pip*" -exec rm -rf {} +

ARG GIT_SHA=unknown
ENV BUILD_SHA=${GIT_SHA}

# Backend source
COPY backend/ .
Expand Down
1 change: 0 additions & 1 deletion backend/api/containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
"previous_docker_id", # internal re-association field, not for API consumers
"image_digest", # raw local image ID (sha256 of config blob), not surfaced in UI
"registry_digest", # raw registry manifest digest, not surfaced in UI
"last_pulled", # not surfaced in UI
}


Expand Down
7 changes: 4 additions & 3 deletions backend/api/system.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import os
from datetime import datetime, timezone

import docker
from fastapi import APIRouter

from build_info import APP_VERSION, BUILD_SHA, APP_START_TIME
from build_info import APP_VERSION, BUILD_CHANNEL, BUILD_DISPLAY, BUILD_LABEL, BUILD_SHA, APP_START_TIME
from database import DB_PATH as _DB_PATH

router = APIRouter(prefix="/api/system", tags=["system"])
Expand All @@ -26,8 +25,10 @@ def get_system_info() -> dict:

return {
"version": APP_VERSION,
"build_channel": os.environ.get("BUILD_CHANNEL", ""),
"build_channel": BUILD_CHANNEL,
"build_label": BUILD_LABEL,
"build_sha": BUILD_SHA,
"display_version": BUILD_DISPLAY,
"uptime_seconds": uptime_seconds,
"db_size_bytes": db_size_bytes,
"docker_connected": docker_connected,
Expand Down
12 changes: 10 additions & 2 deletions backend/build_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@

_version_file = Path("/app/VERSION")
_raw_version = _version_file.read_text().strip() if _version_file.exists() else "dev"
_build_channel = os.environ.get("BUILD_CHANNEL", "")
APP_VERSION = f"{_raw_version}-{_build_channel}" if _build_channel else _raw_version
APP_VERSION = _raw_version
BUILD_CHANNEL = os.environ.get("BUILD_CHANNEL", "")
BUILD_LABEL = os.environ.get("BUILD_LABEL", "")
_raw_sha = os.environ.get("BUILD_SHA", "")
BUILD_SHA: str | None = _raw_sha if _raw_sha and _raw_sha != "unknown" else None
BUILD_DISPLAY = (
f"{BUILD_LABEL} · {BUILD_SHA}"
if BUILD_LABEL and BUILD_SHA
else BUILD_LABEL
or (f"{BUILD_CHANNEL} · {BUILD_SHA}" if BUILD_CHANNEL and BUILD_SHA else "")
or (BUILD_CHANNEL if BUILD_CHANNEL else f"v{APP_VERSION}")
)

APP_START_TIME = datetime.now(timezone.utc)
10 changes: 8 additions & 2 deletions backend/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

logger = logging.getLogger(__name__)

from build_info import APP_VERSION, BUILD_SHA
from build_info import APP_VERSION, BUILD_CHANNEL, BUILD_DISPLAY, BUILD_LABEL, BUILD_SHA
from database import create_db_and_tables, engine
from api import containers, logs, events, settings, actions, admin, stack_actions, operations, analytics as analytics_router
from api import auth as auth_router
Expand Down Expand Up @@ -168,7 +168,13 @@ def version():
# Intentionally public — version info is useful for unauthenticated users
# (e.g., confirming an upgrade took effect from the login page) and carries
# no meaningful attack surface beyond what's visible in the image tag.
return {"version": APP_VERSION, "build_sha": BUILD_SHA}
return {
"version": APP_VERSION,
"build_channel": BUILD_CHANNEL,
"build_label": BUILD_LABEL,
"build_sha": BUILD_SHA,
"display_version": BUILD_DISPLAY,
}


@app.get("/api/health")
Expand Down
Loading