Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1055ba605 | ||
|
|
5efe0446d5 |
@@ -1173,7 +1173,7 @@ jobs:
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
DEPLOYABLE_BACKEND_REPO="${GITEA_REGISTRY}/darkhelm.org/deployable-backend-staging"
|
DEPLOYABLE_BACKEND_REPO="${GITEA_REGISTRY}/darkhelm.org/plex-playlist-backend-staging"
|
||||||
DEPLOYABLE_BACKEND_TAG_REF="${DEPLOYABLE_BACKEND_REPO}:${HEAD_SHA}"
|
DEPLOYABLE_BACKEND_TAG_REF="${DEPLOYABLE_BACKEND_REPO}:${HEAD_SHA}"
|
||||||
DEPLOYABLE_BACKEND_CACHE_REF="${DEPLOYABLE_BACKEND_REPO}:cache"
|
DEPLOYABLE_BACKEND_CACHE_REF="${DEPLOYABLE_BACKEND_REPO}:cache"
|
||||||
|
|
||||||
@@ -1182,11 +1182,11 @@ jobs:
|
|||||||
DOCKER_BUILDKIT=1 docker build -f Dockerfile.backend \
|
DOCKER_BUILDKIT=1 docker build -f Dockerfile.backend \
|
||||||
--cache-from "${DEPLOYABLE_BACKEND_CACHE_REF}" \
|
--cache-from "${DEPLOYABLE_BACKEND_CACHE_REF}" \
|
||||||
--build-arg BUILDKIT_INLINE_CACHE=1 \
|
--build-arg BUILDKIT_INLINE_CACHE=1 \
|
||||||
-t deployable-backend:"${HEAD_SHA}" .
|
-t plex-playlist-backend:"${HEAD_SHA}" .
|
||||||
bash ./scripts/verify-deployable-image-purity.sh --image deployable-backend:"${HEAD_SHA}" --profile backend
|
bash ./scripts/verify-deployable-image-purity.sh --image plex-playlist-backend:"${HEAD_SHA}" --profile backend
|
||||||
|
|
||||||
docker tag "deployable-backend:${HEAD_SHA}" "${DEPLOYABLE_BACKEND_TAG_REF}"
|
docker tag "plex-playlist-backend:${HEAD_SHA}" "${DEPLOYABLE_BACKEND_TAG_REF}"
|
||||||
docker tag "deployable-backend:${HEAD_SHA}" "${DEPLOYABLE_BACKEND_CACHE_REF}"
|
docker tag "plex-playlist-backend:${HEAD_SHA}" "${DEPLOYABLE_BACKEND_CACHE_REF}"
|
||||||
|
|
||||||
retry_registry_op push "${DEPLOYABLE_BACKEND_TAG_REF}" 5 4
|
retry_registry_op push "${DEPLOYABLE_BACKEND_TAG_REF}" 5 4
|
||||||
retry_registry_op push "${DEPLOYABLE_BACKEND_CACHE_REF}" 5 4
|
retry_registry_op push "${DEPLOYABLE_BACKEND_CACHE_REF}" 5 4
|
||||||
@@ -1281,7 +1281,7 @@ jobs:
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
DEPLOYABLE_FRONTEND_REPO="${GITEA_REGISTRY}/darkhelm.org/deployable-frontend-staging"
|
DEPLOYABLE_FRONTEND_REPO="${GITEA_REGISTRY}/darkhelm.org/plex-playlist-frontend-staging"
|
||||||
DEPLOYABLE_FRONTEND_TAG_REF="${DEPLOYABLE_FRONTEND_REPO}:${HEAD_SHA}"
|
DEPLOYABLE_FRONTEND_TAG_REF="${DEPLOYABLE_FRONTEND_REPO}:${HEAD_SHA}"
|
||||||
DEPLOYABLE_FRONTEND_CACHE_REF="${DEPLOYABLE_FRONTEND_REPO}:cache"
|
DEPLOYABLE_FRONTEND_CACHE_REF="${DEPLOYABLE_FRONTEND_REPO}:cache"
|
||||||
|
|
||||||
@@ -1291,11 +1291,11 @@ jobs:
|
|||||||
--target production \
|
--target production \
|
||||||
--cache-from "${DEPLOYABLE_FRONTEND_CACHE_REF}" \
|
--cache-from "${DEPLOYABLE_FRONTEND_CACHE_REF}" \
|
||||||
--build-arg BUILDKIT_INLINE_CACHE=1 \
|
--build-arg BUILDKIT_INLINE_CACHE=1 \
|
||||||
-t deployable-frontend:"${HEAD_SHA}" .
|
-t plex-playlist-frontend:"${HEAD_SHA}" .
|
||||||
bash ./scripts/verify-deployable-image-purity.sh --image deployable-frontend:"${HEAD_SHA}" --profile frontend
|
bash ./scripts/verify-deployable-image-purity.sh --image plex-playlist-frontend:"${HEAD_SHA}" --profile frontend
|
||||||
|
|
||||||
docker tag "deployable-frontend:${HEAD_SHA}" "${DEPLOYABLE_FRONTEND_TAG_REF}"
|
docker tag "plex-playlist-frontend:${HEAD_SHA}" "${DEPLOYABLE_FRONTEND_TAG_REF}"
|
||||||
docker tag "deployable-frontend:${HEAD_SHA}" "${DEPLOYABLE_FRONTEND_CACHE_REF}"
|
docker tag "plex-playlist-frontend:${HEAD_SHA}" "${DEPLOYABLE_FRONTEND_CACHE_REF}"
|
||||||
|
|
||||||
retry_registry_op push "${DEPLOYABLE_FRONTEND_TAG_REF}" 5 4
|
retry_registry_op push "${DEPLOYABLE_FRONTEND_TAG_REF}" 5 4
|
||||||
retry_registry_op push "${DEPLOYABLE_FRONTEND_CACHE_REF}" 5 4
|
retry_registry_op push "${DEPLOYABLE_FRONTEND_CACHE_REF}" 5 4
|
||||||
@@ -2617,12 +2617,12 @@ jobs:
|
|||||||
|
|
||||||
if [ -z "${STAGING_BACKEND_DIGEST_REF}" ]; then
|
if [ -z "${STAGING_BACKEND_DIGEST_REF}" ]; then
|
||||||
echo "Staging backend digest output missing; deriving from staging tag ${HEAD_SHA}"
|
echo "Staging backend digest output missing; deriving from staging tag ${HEAD_SHA}"
|
||||||
STAGING_BACKEND_DIGEST_REF="$(resolve_staging_digest_from_tag "${GITEA_REGISTRY}/darkhelm.org/deployable-backend-staging" "${HEAD_SHA}")"
|
STAGING_BACKEND_DIGEST_REF="$(resolve_staging_digest_from_tag "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-backend-staging" "${HEAD_SHA}")"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "${STAGING_FRONTEND_DIGEST_REF}" ]; then
|
if [ -z "${STAGING_FRONTEND_DIGEST_REF}" ]; then
|
||||||
echo "Staging frontend digest output missing; deriving from staging tag ${HEAD_SHA}"
|
echo "Staging frontend digest output missing; deriving from staging tag ${HEAD_SHA}"
|
||||||
STAGING_FRONTEND_DIGEST_REF="$(resolve_staging_digest_from_tag "${GITEA_REGISTRY}/darkhelm.org/deployable-frontend-staging" "${HEAD_SHA}")"
|
STAGING_FRONTEND_DIGEST_REF="$(resolve_staging_digest_from_tag "${GITEA_REGISTRY}/darkhelm.org/plex-playlist-frontend-staging" "${HEAD_SHA}")"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "${STAGING_BACKEND_DIGEST_REF}" ] || [ -z "${STAGING_FRONTEND_DIGEST_REF}" ]; then
|
if [ -z "${STAGING_BACKEND_DIGEST_REF}" ] || [ -z "${STAGING_FRONTEND_DIGEST_REF}" ]; then
|
||||||
@@ -2683,8 +2683,8 @@ jobs:
|
|||||||
|
|
||||||
PREVIOUS_RELEASE_VERSION="$(printf '%s\n' "${RELEASE_TAG_LIST}" | awk -v current="${RELEASE_VERSION}" 'NF {if ($0 == current) {print prev; found=1; exit} prev=$0} END {if (!found) print prev}')"
|
PREVIOUS_RELEASE_VERSION="$(printf '%s\n' "${RELEASE_TAG_LIST}" | awk -v current="${RELEASE_VERSION}" 'NF {if ($0 == current) {print prev; found=1; exit} prev=$0} END {if (!found) print prev}')"
|
||||||
|
|
||||||
RELEASE_BACKEND_REPO="${GITEA_REGISTRY}/darkhelm.org/deployable-backend"
|
RELEASE_BACKEND_REPO="${GITEA_REGISTRY}/darkhelm.org/plex-playlist-backend"
|
||||||
RELEASE_FRONTEND_REPO="${GITEA_REGISTRY}/darkhelm.org/deployable-frontend"
|
RELEASE_FRONTEND_REPO="${GITEA_REGISTRY}/darkhelm.org/plex-playlist-frontend"
|
||||||
|
|
||||||
BACKEND_RELEASE_VERSION_REF="${RELEASE_BACKEND_REPO}:${RELEASE_VERSION}"
|
BACKEND_RELEASE_VERSION_REF="${RELEASE_BACKEND_REPO}:${RELEASE_VERSION}"
|
||||||
BACKEND_RELEASE_TAGGED_REF="${RELEASE_BACKEND_REPO}:${RELEASE_TAGGED_VERSION}"
|
BACKEND_RELEASE_TAGGED_REF="${RELEASE_BACKEND_REPO}:${RELEASE_TAGGED_VERSION}"
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ classifiers = [
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"fastapi==0.139.0",
|
"fastapi==0.139.0",
|
||||||
"sqlalchemy==2.0.51",
|
"sqlalchemy==2.0.51",
|
||||||
"psycopg[binary]==3.2.12",
|
"psycopg[binary]==3.3.4",
|
||||||
"uvicorn==0.51.0"
|
"uvicorn==0.51.0"
|
||||||
]
|
]
|
||||||
description = "Backend service for Plex playlist management"
|
description = "Backend service for Plex playlist management"
|
||||||
|
|||||||
1300
backend/uv.lock
generated
1300
backend/uv.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,7 @@ services:
|
|||||||
retries: 12
|
retries: 12
|
||||||
|
|
||||||
backend:
|
backend:
|
||||||
image: ${DEPLOYABLE_BACKEND_IMAGE:-deployable-backend:local}
|
image: ${DEPLOYABLE_BACKEND_IMAGE:-plex-playlist-backend:local}
|
||||||
environment:
|
environment:
|
||||||
DATABASE_URL: ${DB_URL:-postgresql://plex_user:plex_password@database:5432/plex_playlist}
|
DATABASE_URL: ${DB_URL:-postgresql://plex_user:plex_password@database:5432/plex_playlist}
|
||||||
ENVIRONMENT: production
|
ENVIRONMENT: production
|
||||||
@@ -22,7 +22,7 @@ services:
|
|||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
image: ${DEPLOYABLE_FRONTEND_IMAGE:-deployable-frontend:local}
|
image: ${DEPLOYABLE_FRONTEND_IMAGE:-plex-playlist-frontend:local}
|
||||||
depends_on:
|
depends_on:
|
||||||
backend:
|
backend:
|
||||||
condition: service_started
|
condition: service_started
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ services:
|
|||||||
retries: 12
|
retries: 12
|
||||||
|
|
||||||
backend:
|
backend:
|
||||||
image: ${DEPLOYABLE_BACKEND_IMAGE:-deployable-backend:local}
|
image: ${DEPLOYABLE_BACKEND_IMAGE:-plex-playlist-backend:local}
|
||||||
environment:
|
environment:
|
||||||
DATABASE_URL: ${DB_URL:-postgresql://plex_user:plex_password@database:5432/plex_playlist}
|
DATABASE_URL: ${DB_URL:-postgresql://plex_user:plex_password@database:5432/plex_playlist}
|
||||||
ENVIRONMENT: production
|
ENVIRONMENT: production
|
||||||
|
|||||||
@@ -72,12 +72,12 @@
|
|||||||
### **Current Release Lifecycle (2026-07)**
|
### **Current Release Lifecycle (2026-07)**
|
||||||
|
|
||||||
- Runtime deployable images are published first to staging repositories:
|
- Runtime deployable images are published first to staging repositories:
|
||||||
- `deployable-backend-staging`
|
- `plex-playlist-backend-staging`
|
||||||
- `deployable-frontend-staging`
|
- `plex-playlist-frontend-staging`
|
||||||
- Runtime validation (`Runtime Black-Box Integration Tests` and `End-to-End Tests`) must pass before release tagging.
|
- Runtime validation (`Runtime Black-Box Integration Tests` and `End-to-End Tests`) must pass before release tagging.
|
||||||
- `Promote Release Images` retags validated staging artifacts to release repositories, but only on automated `push` runs to `main`:
|
- `Promote Release Images` retags validated staging artifacts to release repositories, but only on automated `push` runs to `main`:
|
||||||
- `deployable-backend`
|
- `plex-playlist-backend`
|
||||||
- `deployable-frontend`
|
- `plex-playlist-frontend`
|
||||||
- Published release tags:
|
- Published release tags:
|
||||||
- `latest`
|
- `latest`
|
||||||
- `v<major>.<minor>.0`
|
- `v<major>.<minor>.0`
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ automation work under epic #66.
|
|||||||
Lifecycle note:
|
Lifecycle note:
|
||||||
|
|
||||||
- CI first builds deployable runtime artifacts in staging repositories
|
- CI first builds deployable runtime artifacts in staging repositories
|
||||||
(`deployable-backend-staging`, `deployable-frontend-staging`).
|
(`plex-playlist-backend-staging`, `plex-playlist-frontend-staging`).
|
||||||
- After integration and E2E validation pass, CI promotes those immutable
|
- After integration and E2E validation pass, CI promotes those immutable
|
||||||
artifacts to release repositories (`deployable-backend`,
|
artifacts to release repositories (`plex-playlist-backend`,
|
||||||
`deployable-frontend`) via tag promotion.
|
`plex-playlist-frontend`) via tag promotion.
|
||||||
|
|
||||||
Included:
|
Included:
|
||||||
|
|
||||||
|
|||||||
@@ -411,11 +411,11 @@ The pipeline is intentionally staged so expensive image jobs run only after sour
|
|||||||
2. Source + audit lanes:
|
2. Source + audit lanes:
|
||||||
`Source Checks` and `Dependency Audits (Informational)` run after producer completion. Audit failures are intentionally non-blocking so both frontend and backend audits always report.
|
`Source Checks` and `Dependency Audits (Informational)` run after producer completion. Audit failures are intentionally non-blocking so both frontend and backend audits always report.
|
||||||
3. Runtime image lanes:
|
3. Runtime image lanes:
|
||||||
`Build Release Images` publishes `deployable-backend-staging` and `deployable-frontend-staging`; `Build Tester Images` publishes integration/e2e tester images; then `Production Images Complete` gates downstream runtime tests.
|
`Build Release Images` publishes `plex-playlist-backend-staging` and `plex-playlist-frontend-staging`; `Build Tester Images` publishes integration/e2e tester images; then `Production Images Complete` gates downstream runtime tests.
|
||||||
4. Runtime validation lanes:
|
4. Runtime validation lanes:
|
||||||
`Runtime Black-Box Integration Tests` and `End-to-End Tests` validate staged runtime artifacts.
|
`Runtime Black-Box Integration Tests` and `End-to-End Tests` validate staged runtime artifacts.
|
||||||
5. Promotion lane:
|
5. Promotion lane:
|
||||||
`Promote Release Images` runs only for automated `push` events on `main`. It retags validated staging artifacts to release repos (`deployable-backend`, `deployable-frontend`) with `latest`, `v<major>.<minor>.0`, `v<major>.<minor>.<patch>`, and `v<major>.<minor>.<patch>-<7-char-short-sha>` tags. If the `main` commit is untagged, CI creates the next patch tag automatically; if no prior semver tag exists, the bootstrap baseline is `v0.0.0`.
|
`Promote Release Images` runs only for automated `push` events on `main`. It retags validated staging artifacts to release repos (`plex-playlist-backend`, `plex-playlist-frontend`) with `latest`, `v<major>.<minor>.0`, `v<major>.<minor>.<patch>`, and `v<major>.<minor>.<patch>-<7-char-short-sha>` tags. If the `main` commit is untagged, CI creates the next patch tag automatically; if no prior semver tag exists, the bootstrap baseline is `v0.0.0`.
|
||||||
6. Postmortem lanes:
|
6. Postmortem lanes:
|
||||||
targeted postmortem jobs run when key lanes fail to capture diagnostics even when primary jobs fail early.
|
targeted postmortem jobs run when key lanes fail to capture diagnostics even when primary jobs fail early.
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ PROJECT_NAME="${COMPOSE_PROJECT_NAME:-plex-e2e-local}"
|
|||||||
|
|
||||||
mkdir -p "${ROOT_DIR}/frontend/.playwright-artifacts"
|
mkdir -p "${ROOT_DIR}/frontend/.playwright-artifacts"
|
||||||
|
|
||||||
export DEPLOYABLE_BACKEND_IMAGE="${DEPLOYABLE_BACKEND_IMAGE:-deployable-backend:local}"
|
export DEPLOYABLE_BACKEND_IMAGE="${DEPLOYABLE_BACKEND_IMAGE:-plex-playlist-backend:local}"
|
||||||
export DEPLOYABLE_FRONTEND_IMAGE="${DEPLOYABLE_FRONTEND_IMAGE:-deployable-frontend:local}"
|
export DEPLOYABLE_FRONTEND_IMAGE="${DEPLOYABLE_FRONTEND_IMAGE:-plex-playlist-frontend:local}"
|
||||||
export DB_PASSWORD="${DB_PASSWORD:-plex_password}"
|
export DB_PASSWORD="${DB_PASSWORD:-plex_password}"
|
||||||
export DB_URL="${DB_URL:-postgresql://plex_user:${DB_PASSWORD}@database:5432/plex_playlist}"
|
export DB_URL="${DB_URL:-postgresql://plex_user:${DB_PASSWORD}@database:5432/plex_playlist}"
|
||||||
export E2E_ARTIFACT_DIR="${E2E_ARTIFACT_DIR:-${ROOT_DIR}/frontend/.playwright-artifacts}"
|
export E2E_ARTIFACT_DIR="${E2E_ARTIFACT_DIR:-${ROOT_DIR}/frontend/.playwright-artifacts}"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|||||||
COMPOSE_FILE="${ROOT_DIR}/compose.ci.integration.yml"
|
COMPOSE_FILE="${ROOT_DIR}/compose.ci.integration.yml"
|
||||||
PROJECT_NAME="${COMPOSE_PROJECT_NAME:-plex-int-local}"
|
PROJECT_NAME="${COMPOSE_PROJECT_NAME:-plex-int-local}"
|
||||||
|
|
||||||
export DEPLOYABLE_BACKEND_IMAGE="${DEPLOYABLE_BACKEND_IMAGE:-deployable-backend:local}"
|
export DEPLOYABLE_BACKEND_IMAGE="${DEPLOYABLE_BACKEND_IMAGE:-plex-playlist-backend:local}"
|
||||||
export DB_PASSWORD="${DB_PASSWORD:-plex_password}"
|
export DB_PASSWORD="${DB_PASSWORD:-plex_password}"
|
||||||
export DB_URL="${DB_URL:-postgresql://plex_user:${DB_PASSWORD}@database:5432/plex_playlist}"
|
export DB_URL="${DB_URL:-postgresql://plex_user:${DB_PASSWORD}@database:5432/plex_playlist}"
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ cleanup() {
|
|||||||
|
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
|
|
||||||
echo "Running runtime integration checks against deployable backend image via compose"
|
echo "Running runtime integration checks against plex-playlist backend image via compose"
|
||||||
echo "DEPLOYABLE_BACKEND_IMAGE=${DEPLOYABLE_BACKEND_IMAGE}"
|
echo "DEPLOYABLE_BACKEND_IMAGE=${DEPLOYABLE_BACKEND_IMAGE}"
|
||||||
|
|
||||||
docker compose -p "${PROJECT_NAME}" -f "${COMPOSE_FILE}" up -d database backend
|
docker compose -p "${PROJECT_NAME}" -f "${COMPOSE_FILE}" up -d database backend
|
||||||
|
|||||||
Reference in New Issue
Block a user