Browse Source

make it easier to query for release

imwald
Silberengel 4 weeks ago
parent
commit
1895202092
  1. 26
      Dockerfile
  2. 6
      docker-compose.prod.yml
  3. 4
      package-lock.json
  4. 2
      package.json
  5. 9
      scripts/README-deploy.md
  6. 8
      scripts/build-and-push-prod.sh
  7. 26
      scripts/write-build-version-json.mjs

26
Dockerfile

@ -13,6 +13,13 @@ ENV VITE_LANGUAGE_TOOL_URL=${VITE_LANGUAGE_TOOL_URL}
ARG VITE_TRANSLATE_URL ARG VITE_TRANSLATE_URL
ENV VITE_TRANSLATE_URL=${VITE_TRANSLATE_URL} ENV VITE_TRANSLATE_URL=${VITE_TRANSLATE_URL}
ARG APP_VERSION=unknown
ARG GIT_COMMIT=unknown
ARG BUILD_TIME
ENV APP_VERSION=${APP_VERSION}
ENV GIT_COMMIT=${GIT_COMMIT}
ENV BUILD_TIME=${BUILD_TIME}
WORKDIR /app WORKDIR /app
# Copy package files first # Copy package files first
@ -21,12 +28,20 @@ RUN npm install
# Copy the source code to prevent invaliding cache whenever there is a change in the code # Copy the source code to prevent invaliding cache whenever there is a change in the code
COPY . . COPY . .
RUN npm run build RUN npm run build \
&& node scripts/write-build-version-json.mjs
# Step 2: Final container with Nginx and embedded config # Step 2: Final container with Nginx and embedded config
FROM nginx:alpine FROM nginx:alpine
RUN apk add --no-cache jq ARG APP_VERSION=unknown
ARG GIT_COMMIT=unknown
RUN apk add --no-cache jq wget
LABEL org.opencontainers.image.title="imwald-jumble" \
org.opencontainers.image.version="${APP_VERSION}" \
org.opencontainers.image.revision="${GIT_COMMIT}"
# Copy only the generated static files # Copy only the generated static files
COPY --from=builder /app/dist /usr/share/nginx/html COPY --from=builder /app/dist /usr/share/nginx/html
@ -39,6 +54,13 @@ RUN printf "server {\n\
server_name localhost;\n\ server_name localhost;\n\
root /usr/share/nginx/html;\n\ root /usr/share/nginx/html;\n\
index index.html;\n\ index index.html;\n\
\n\
location = /health.json {\n\
add_header Cache-Control \"no-cache, no-store, must-revalidate\";\n\
add_header Pragma \"no-cache\";\n\
expires off;\n\
try_files \$uri =404;\n\
}\n\
\n\ \n\
# PWA: service worker + precache manifest must not be long-cached or browsers never see\n\ # PWA: service worker + precache manifest must not be long-cached or browsers never see\n\
# updates (VersionUpdateBanner stays hidden; About shows an old APP_VERSION from precache).\n\ # updates (VersionUpdateBanner stays hidden; About shows an old APP_VERSION from precache).\n\

6
docker-compose.prod.yml

@ -35,6 +35,12 @@ services:
options: options:
max-size: "10m" max-size: "10m"
max-file: "3" max-file: "3"
healthcheck:
test: ['CMD', 'wget', '-qO-', 'http://127.0.0.1/health.json']
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
deploy: deploy:
resources: resources:
limits: limits:

4
package-lock.json generated

@ -1,12 +1,12 @@
{ {
"name": "imwald", "name": "imwald",
"version": "23.13.5", "version": "23.13.6",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "imwald", "name": "imwald",
"version": "23.13.5", "version": "23.13.6",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@asciidoctor/core": "^3.0.4", "@asciidoctor/core": "^3.0.4",

2
package.json

@ -1,6 +1,6 @@
{ {
"name": "imwald", "name": "imwald",
"version": "23.13.5", "version": "23.13.6",
"description": "Imwald — a user-friendly Nostr client focused on relay feed browsing, publications, and relay discovery", "description": "Imwald — a user-friendly Nostr client focused on relay feed browsing, publications, and relay discovery",
"private": true, "private": true,
"type": "module", "type": "module",

9
scripts/README-deploy.md

@ -75,9 +75,18 @@ Images default to `:latest`; to pin a version, set image tags in `docker-compose
# Status # Status
docker compose -f docker-compose.prod.yml ps docker compose -f docker-compose.prod.yml ps
# Release running in the app container (JSON)
curl -sS http://127.0.0.1:8089/health.json | jq .
# Same via Docker healthcheck file:
docker exec imwald-jumble wget -qO- http://127.0.0.1/health.json | jq .
# Image labels (after pull; matches package.json at build time)
docker inspect imwald-jumble --format 'version={{index .Config.Labels "org.opencontainers.image.version"}} commit={{index .Config.Labels "org.opencontainers.image.revision"}}'
# Logs # Logs
docker compose -f docker-compose.prod.yml logs -f docker compose -f docker-compose.prod.yml logs -f
# Stop # Stop
docker compose -f docker-compose.prod.yml down docker compose -f docker-compose.prod.yml down
``` ```
`health.json` is baked into each app image build (`version`, `gitCommit`, `builtAt`). Public site: `https://<your-host>/health.json` if Apache proxies `/` to port 8089.

8
scripts/build-and-push-prod.sh

@ -35,12 +35,18 @@ READ_ALOUD_TTS_URL="${READ_ALOUD_TTS_URL:-/api/piper-tts}"
LANGUAGE_TOOL_URL="${LANGUAGE_TOOL_URL-/api/languagetool}" LANGUAGE_TOOL_URL="${LANGUAGE_TOOL_URL-/api/languagetool}"
TRANSLATE_URL="${TRANSLATE_URL-/api/translate}" TRANSLATE_URL="${TRANSLATE_URL-/api/translate}"
echo "Building main app (version: $VERSION, VITE_PROXY_SERVER=$PROXY_ORIGIN, VITE_READ_ALOUD_TTS_URL=$READ_ALOUD_TTS_URL, VITE_LANGUAGE_TOOL_URL=$LANGUAGE_TOOL_URL, VITE_TRANSLATE_URL=$TRANSLATE_URL)" GIT_COMMIT="$(git rev-parse --short HEAD 2>/dev/null || echo unknown)"
BUILD_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "Building main app (version: $VERSION, commit: $GIT_COMMIT, VITE_PROXY_SERVER=$PROXY_ORIGIN, VITE_READ_ALOUD_TTS_URL=$READ_ALOUD_TTS_URL, VITE_LANGUAGE_TOOL_URL=$LANGUAGE_TOOL_URL, VITE_TRANSLATE_URL=$TRANSLATE_URL)"
docker build \ docker build \
--build-arg "VITE_PROXY_SERVER=$PROXY_ORIGIN" \ --build-arg "VITE_PROXY_SERVER=$PROXY_ORIGIN" \
--build-arg "VITE_READ_ALOUD_TTS_URL=$READ_ALOUD_TTS_URL" \ --build-arg "VITE_READ_ALOUD_TTS_URL=$READ_ALOUD_TTS_URL" \
--build-arg "VITE_LANGUAGE_TOOL_URL=$LANGUAGE_TOOL_URL" \ --build-arg "VITE_LANGUAGE_TOOL_URL=$LANGUAGE_TOOL_URL" \
--build-arg "VITE_TRANSLATE_URL=$TRANSLATE_URL" \ --build-arg "VITE_TRANSLATE_URL=$TRANSLATE_URL" \
--build-arg "APP_VERSION=$VERSION" \
--build-arg "GIT_COMMIT=$GIT_COMMIT" \
--build-arg "BUILD_TIME=$BUILD_TIME" \
-t "$IMAGE_APP:latest" -t "$IMAGE_APP:$VERSION" . -t "$IMAGE_APP:latest" -t "$IMAGE_APP:$VERSION" .
echo "Building NIP-66 monitor (version: $VERSION)" echo "Building NIP-66 monitor (version: $VERSION)"

26
scripts/write-build-version-json.mjs

@ -0,0 +1,26 @@
/**
* Writes dist/health.json after `npm run build` (Docker image release metadata).
* Env: APP_VERSION, GIT_COMMIT, BUILD_TIME (ISO); falls back to package.json + unknown.
*/
import { readFileSync, writeFileSync } from 'node:fs'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
const root = join(dirname(fileURLToPath(import.meta.url)), '..')
const pkg = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'))
const version = process.env.APP_VERSION?.trim() || pkg.version
const gitCommit = process.env.GIT_COMMIT?.trim() || 'unknown'
const builtAt = process.env.BUILD_TIME?.trim() || new Date().toISOString()
const payload = {
status: 'ok',
name: pkg.name,
version,
gitTag: `v${version}`,
gitCommit,
builtAt
}
const out = join(root, 'dist', 'health.json')
writeFileSync(out, `${JSON.stringify(payload)}\n`)
console.log(`Wrote ${out}: v${version} (${gitCommit})`)
Loading…
Cancel
Save