Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ English/Vietnamese pair. Taxonomy-only work is a separate structural PR.
- [x] Create the durable page register in `apps/docs/AUTHORING.md`.
- [x] Transfer unfinished content follow-ups from the completed portal
increment.
- [ ] Merge the program foundation and taxonomy migration.
- [x] Merge the program foundation and taxonomy migration.

## Taxonomy Migration

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,20 @@ required version remains the merge authority.

## Delivery

Pending PR review, merge, immutable build, deployment, and live verification.
- PR #134 merged to `main` as
`e2a376358048b85d465532e4f3f8a4bfddeac138`.
- PR CI run `30464083979` and main CI run `30464387882` passed, including the
Node 24 public-docs job and aggregate CI Gate.
- Immutable image build, scan, release recording, and publication passed in run
`30464628816`.
- Initial deploy run `30464858925` started a healthy candidate, then safely
restored `fb1c176b9503a0692a0781b0fa924ac7334e58d3`. The deployment smoke still
expected the retired `/docs/overview` root, and rollback incorrectly compared
the restored old image with the candidate manifest.
- The follow-up repair makes smoke checks taxonomy-stable and limits the
candidate-manifest publication audit to the candidate. Forced-canary rollback
now proves the previous image is checked without applying the candidate
manifest to it.

Pending repair PR, immutable rebuild, successful deployment, and live
verification.
13 changes: 10 additions & 3 deletions infrastructure/deployment/scripts/deploy-docs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ compose_file="${ORGMEMORY_DOCS_COMPOSE_FILE:-$repo_root/infrastructure/deploymen
environment_file="${ORGMEMORY_DOCS_ENV_FILE:-$repo_root/.env.docs.production}"
runtime_root="${ORGMEMORY_DOCS_RUNTIME_ROOT:-/apps/orgmemory-runtime/docs}"
smoke_script="${ORGMEMORY_DOCS_SMOKE_SCRIPT:-$repo_root/infrastructure/deployment/scripts/smoke-docs.sh}"
publication_verifier="${ORGMEMORY_DOCS_PUBLICATION_VERIFIER:-$repo_root/infrastructure/deployment/scripts/verify-docs-publication.py}"
lock_file="$runtime_root/deploy.lock"
release_stamp="$(date -u +%Y%m%dT%H%M%SZ)"
release_directory="$runtime_root/releases/$release_stamp"
Expand Down Expand Up @@ -98,16 +99,20 @@ replace_image_reference() {

run_smoke() {
local public_url
local verify_current_publication="${1:-true}"

ORGMEMORY_REPO_ROOT="$repo_root" \
ORGMEMORY_DOCS_COMPOSE_FILE="$compose_file" \
ORGMEMORY_DOCS_ENV_FILE="$environment_file" \
"$smoke_script"

if [[ "${ORGMEMORY_DOCS_REQUIRE_PUBLIC_SMOKE:-false}" == "true" ]]; then
if [[
"${ORGMEMORY_DOCS_REQUIRE_PUBLIC_SMOKE:-false}" == "true" &&
"$verify_current_publication" == "true"
]]; then
public_url="${ORGMEMORY_DOCS_PUBLIC_URL:-$(read_environment_value "$environment_file" ORGMEMORY_DOCS_PUBLIC_URL)}"
python3 \
"$repo_root/infrastructure/deployment/scripts/verify-docs-publication.py" \
"$publication_verifier" \
"$public_url"
fi
}
Expand All @@ -121,7 +126,9 @@ rollback() {
install -m 0600 "$current_environment_file" "$environment_file"
"${compose[@]}" pull orgmemory-docs
"${compose[@]}" up -d --wait --wait-timeout 60 orgmemory-docs
run_smoke
# The previous image may expose an older taxonomy. Verify its stable
# runtime contract, but do not compare it with the candidate manifest.
run_smoke false
else
install -m 0600 "$previous_environment" "$environment_file"
"${compose[@]}" down
Expand Down
7 changes: 3 additions & 4 deletions infrastructure/deployment/scripts/smoke-docs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ check_public_route() {

check_public_root_redirect() {
local result
local expected_prefix

result="$(
curl --fail --location --silent --show-error \
Expand All @@ -88,14 +89,13 @@ check_public_root_redirect() {
--write-out '%{http_code} %{url_effective}' \
"${public_url%/}/"
)"
[[ "$result" == "200 ${public_url%/}/docs/overview" ]]
expected_prefix="200 ${public_url%/}/docs/"
[[ "$result" == "$expected_prefix"* ]]
}

wait_for_internal_health
for route in \
"/docs/overview" \
"/docs/architecture-security/system-description" \
"/docs/developers/api-reference/search-catalog" \
"/api/search?query=OpenFGA" \
"/llms.txt"; do
check_internal_route "$route"
Expand All @@ -109,7 +109,6 @@ if [[ "$require_public_smoke" == "true" ]]; then
check_public_root_redirect
for route in \
"/docs/architecture-security/system-description" \
"/docs/developers/api-reference/search-catalog" \
"/api/search?query=OpenFGA" \
"/llms.txt"; do
check_public_route "$route"
Expand Down
34 changes: 29 additions & 5 deletions infrastructure/deployment/scripts/test-deploy-docs-rollback.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,19 @@ environment_file="$temporary_root/.env.docs.production"
compose_file="$temporary_root/compose.docs.yaml"
stub_bin="$temporary_root/bin"
smoke_script="$temporary_root/smoke.sh"
publication_verifier="$temporary_root/verify-publication.py"
production_smoke_script="$repo_root/infrastructure/deployment/scripts/smoke-docs.sh"
docker_log="$temporary_root/docker.log"
curl_log="$temporary_root/curl.log"
smoke_count="$temporary_root/smoke.count"
verifier_count="$temporary_root/verifier.count"
old_sha="1111111111111111111111111111111111111111"
candidate_sha="2222222222222222222222222222222222222222"

install -d -m 0700 "$runtime_root/releases" "$stub_bin"
printf 'ORGMEMORY_DOCS_IMAGE=ghcr.io/kl3init/orgmemory-docs:sha-%s\n' \
"$old_sha" > "$environment_file"
printf 'ORGMEMORY_DOCS_PUBLIC_URL=https://docs.example.test\n' >> "$environment_file"
chmod 0600 "$environment_file"
install -m 0600 "$environment_file" "$runtime_root/current.env"
printf '%s\n' "$old_sha" > "$runtime_root/current-commit"
Expand All @@ -48,21 +51,33 @@ if [[ -f "$ORGMEMORY_DOCS_TEST_SMOKE_COUNT" ]]; then
fi
count=$((count + 1))
printf '%s\n' "$count" > "$ORGMEMORY_DOCS_TEST_SMOKE_COUNT"
if [[ "$count" -eq 1 ]]; then
exit 1
fi
SH
chmod +x "$smoke_script"

cat > "$publication_verifier" <<'PY'
#!/usr/bin/env python3
import os
from pathlib import Path

count_path = Path(os.environ["ORGMEMORY_DOCS_TEST_VERIFIER_COUNT"])
count = int(count_path.read_text() if count_path.exists() else "0") + 1
count_path.write_text(f"{count}\n")
raise SystemExit(1)
PY
chmod +x "$publication_verifier"

set +e
PATH="$stub_bin:$PATH" \
ORGMEMORY_REPO_ROOT="$repo_root" \
ORGMEMORY_DOCS_COMPOSE_FILE="$compose_file" \
ORGMEMORY_DOCS_ENV_FILE="$environment_file" \
ORGMEMORY_DOCS_RUNTIME_ROOT="$runtime_root" \
ORGMEMORY_DOCS_SMOKE_SCRIPT="$smoke_script" \
ORGMEMORY_DOCS_PUBLICATION_VERIFIER="$publication_verifier" \
ORGMEMORY_DOCS_REQUIRE_PUBLIC_SMOKE=true \
ORGMEMORY_DOCS_TEST_DOCKER_LOG="$docker_log" \
ORGMEMORY_DOCS_TEST_SMOKE_COUNT="$smoke_count" \
ORGMEMORY_DOCS_TEST_VERIFIER_COUNT="$verifier_count" \
"$deploy_script" "$candidate_sha"
status="$?"
set -e
Expand All @@ -76,6 +91,7 @@ grep -Fxq \
"ORGMEMORY_DOCS_IMAGE=ghcr.io/kl3init/orgmemory-docs:sha-$old_sha" \
"$environment_file"
grep -Fxq "2" "$smoke_count"
grep -Fxq "1" "$verifier_count"

if grep -Eq \
'(^|[[:space:]])(api|worker|mcp|web|keycloak|postgres)([[:space:]]|$)' \
Expand All @@ -95,7 +111,7 @@ set -euo pipefail
printf '%s\n' "$*" >> "$ORGMEMORY_DOCS_TEST_CURL_LOG"
url="${!#}"
if [[ "$url" == "https://docs.example.test/" ]]; then
printf '200 https://docs.example.test/docs/overview'
printf '200 https://docs.example.test/docs/getting-started'
else
printf '200'
fi
Expand All @@ -118,11 +134,19 @@ ORGMEMORY_DOCS_TEST_CURL_LOG="$curl_log" \
ORGMEMORY_DOCS_TEST_DOCKER_LOG="$docker_log" \
"$production_smoke_script"

grep -Fq 'http://127.0.0.1:3000/docs/overview' "$docker_log"
grep -Fq \
'http://127.0.0.1:3000/docs/architecture-security/system-description' \
"$docker_log"
if grep -Eq 'http://127\.0\.0\.1:3000/$' "$docker_log"; then
printf 'Internal smoke still treats the redirecting root as a document.\n' >&2
exit 1
fi
if grep -Eq \
'http://127\.0\.0\.1:3000/docs/(overview|developers/api-reference)' \
"$docker_log"; then
printf 'Internal smoke still depends on the retired taxonomy.\n' >&2
exit 1
fi
grep -Fq -- '--location' "$curl_log"
grep -Fq 'https://docs.example.test/' "$curl_log"

Expand Down