feature/loaded-model-indicator #2
34
CHANGELOG.md
Normal file
34
CHANGELOG.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to finrod are documented here.
|
||||
|
||||
Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
||||
Versioning: [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.1.0] - 2026-06-09
|
||||
|
||||
First release. Stateless translator UI that proxies streaming requests to
|
||||
Ollama on radagast.
|
||||
|
||||
### Added
|
||||
- FastAPI backend with three endpoints:
|
||||
- `GET /api/models` — filtered (`gemma,aya` by default) list from Ollama's `/api/tags`
|
||||
- `POST /api/translate` — streams Ollama's NDJSON `/api/generate` response back to the browser
|
||||
- `GET /api/loaded` — proxies Ollama's `/api/ps` for the currently-loaded model
|
||||
- `GET /healthz` — for Kubernetes probes
|
||||
- Single-page UI:
|
||||
- Source / target / model dropdowns (30+ languages, "Auto-detect" source)
|
||||
- Token-by-token streaming into the output pane with a blinking caret
|
||||
- Live status line: spinner while waiting for first token, pulsing dot during streaming, elapsed time and token count
|
||||
- Glowing border on the output pane during streaming
|
||||
- Loaded-model indicator (`● ` prefix in dropdown, "Hot: … — unloads in Xm" status line); refreshes on page load, on translation completion, and 500 ms after typing pauses
|
||||
- ⌘/Ctrl-Enter to translate from the input
|
||||
- Dark mode, inline SVG favicon (Star of Fëanor)
|
||||
- Dockerfile: two-stage `uv` build, slim Python 3.13 runtime
|
||||
- `build.sh`: multi-arch (amd64 + arm64) manual push to Scaleway, tags `:latest`, `:<git-short-sha>`, and `:<pyproject-version>`
|
||||
- Cluster deploy via the `valinor` repo at `apps/finrod/` (bjw-s app-template, internal-only ingress at `finrod.jpnadas.xyz`)
|
||||
|
||||
### Fixed
|
||||
- Lock against public PyPI explicitly — the workstation's global `uv` config had pointed `uv.lock` sources at the dexterenergy private artifact registry, which 401'd inside Docker
|
||||
27
README.md
27
README.md
@@ -47,14 +47,29 @@ Then on every change:
|
||||
./build.sh
|
||||
```
|
||||
|
||||
That builds `linux/amd64,linux/arm64` and pushes `rg.nl-ams.scw.cloud/valinor/finrod:{latest, <git-short-sha>}`. Take note of the short SHA it prints — that's what you pin in valinor.
|
||||
That builds `linux/amd64,linux/arm64` and pushes three tags:
|
||||
- `:latest` — moving pointer
|
||||
- `:<git-short-sha>` — immutable, traceable
|
||||
- `:<pyproject-version>` (e.g. `:0.1.0`) — semver
|
||||
|
||||
## Deploy
|
||||
|
||||
Cluster manifests live in `valinor/apps/finrod/` (bjw-s app-template, internal-only ingress at `finrod.jpnadas.xyz`). To roll out a new build:
|
||||
Cluster manifests live in `valinor/apps/finrod/` (bjw-s app-template, internal-only ingress at `finrod.jpnadas.xyz`). To roll out a new build, bump `tag:` in `valinor/apps/finrod/values.yaml` to the new semver on a branch → PR → merge → ArgoCD syncs.
|
||||
|
||||
1. `./build.sh` here — get the SHA
|
||||
2. Bump `tag:` in `valinor/apps/finrod/values.yaml` to that SHA on a branch
|
||||
3. Merge → ArgoCD syncs the new image
|
||||
## Release workflow
|
||||
|
||||
Using `:latest` works for the first deploy (the pull policy is `Always`) but pinning to a SHA on each rollout gives you trivial rollback via git revert.
|
||||
This project uses [Semantic Versioning](https://semver.org/) and keeps a human-edited [CHANGELOG.md](./CHANGELOG.md).
|
||||
|
||||
To cut a release:
|
||||
|
||||
1. On a branch, edit `CHANGELOG.md`: move accumulated `[Unreleased]` notes into a new `## [X.Y.Z] - YYYY-MM-DD` section.
|
||||
2. Bump `version` in `pyproject.toml` to `X.Y.Z`.
|
||||
3. PR → merge to `main`.
|
||||
4. Tag the merge commit:
|
||||
```sh
|
||||
git checkout main && git pull
|
||||
git tag -a vX.Y.Z -m "vX.Y.Z"
|
||||
git push origin vX.Y.Z
|
||||
```
|
||||
5. `./build.sh` — the image now also gets `:X.Y.Z` (read from `pyproject.toml`).
|
||||
6. In `valinor`, bump `apps/finrod/values.yaml` `tag:` from the previous version to `X.Y.Z` on a branch → PR → ArgoCD picks it up.
|
||||
|
||||
23
build.sh
23
build.sh
@@ -9,20 +9,24 @@
|
||||
# docker login rg.nl-ams.scw.cloud -u nologin -p <SCW_SECRET_KEY>
|
||||
#
|
||||
# Usage:
|
||||
# ./build.sh # tags :latest and :<short-sha>
|
||||
# TAG=v0.2.0 ./build.sh # additional explicit tag
|
||||
# ./build.sh
|
||||
#
|
||||
# Always tags:
|
||||
# :latest — moving pointer
|
||||
# :<git-short-sha> — immutable, traceable to a commit
|
||||
# :<pyproject-version> — semver from pyproject.toml (e.g. :0.1.0)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
REGISTRY="${REGISTRY:-rg.nl-ams.scw.cloud/valinor}"
|
||||
IMAGE="${REGISTRY}/finrod"
|
||||
SHA="$(git rev-parse --short HEAD)"
|
||||
TAGS=(-t "${IMAGE}:latest" -t "${IMAGE}:${SHA}")
|
||||
if [[ -n "${TAG:-}" ]]; then
|
||||
TAGS+=(-t "${IMAGE}:${TAG}")
|
||||
fi
|
||||
VERSION="$(awk -F\" '/^version =/ {print $2; exit}' pyproject.toml)"
|
||||
: "${VERSION:?Could not read version from pyproject.toml}"
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
TAGS=(-t "${IMAGE}:latest" -t "${IMAGE}:${SHA}" -t "${IMAGE}:${VERSION}")
|
||||
|
||||
docker buildx build \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
@@ -31,4 +35,7 @@ docker buildx build \
|
||||
.
|
||||
|
||||
echo
|
||||
echo "Pushed: ${IMAGE}:{latest,${SHA}${TAG:+,${TAG}}}"
|
||||
echo "Pushed:"
|
||||
echo " ${IMAGE}:latest"
|
||||
echo " ${IMAGE}:${SHA}"
|
||||
echo " ${IMAGE}:${VERSION}"
|
||||
|
||||
Reference in New Issue
Block a user