Fix: harden local dev startup flow
This commit is contained in:
@@ -6,6 +6,9 @@ WORKDIR /app
|
|||||||
|
|
||||||
RUN apk add --no-cache ca-certificates curl git tzdata && update-ca-certificates
|
RUN apk add --no-cache ca-certificates curl git tzdata && update-ca-certificates
|
||||||
|
|
||||||
|
RUN mkdir -p /tmp/home /tmp/go/pkg/mod /tmp/go-build \
|
||||||
|
&& chmod 0777 /tmp/home /tmp/go /tmp/go/pkg /tmp/go/pkg/mod /tmp/go-build
|
||||||
|
|
||||||
COPY go.mod go.sum ./
|
COPY go.mod go.sum ./
|
||||||
RUN go mod download
|
RUN go mod download
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +1,39 @@
|
|||||||
project_root := justfile_directory()
|
project_root := justfile_directory()
|
||||||
backend_dir := project_root + "/Backend"
|
backend_dir := project_root + "/Backend"
|
||||||
|
common_sh := project_root + "/Commands/Local/scripts/common.sh"
|
||||||
|
posix_root := project_root + "/POSIX"
|
||||||
|
|
||||||
# Apply embedded database migrations.
|
# Apply embedded database migrations.
|
||||||
migrate-up:
|
migrate-up:
|
||||||
|
bash -c 'source "{{common_sh}}"; ensure_posix_root "{{project_root}}" "{{posix_root}}"'
|
||||||
cd '{{backend_dir}}' && go run ./cmd/migrate up
|
cd '{{backend_dir}}' && go run ./cmd/migrate up
|
||||||
|
|
||||||
# Roll back the most recent embedded database migration.
|
# Roll back the most recent embedded database migration (confirmation required).
|
||||||
migrate-down:
|
migrate-down:
|
||||||
|
bash -c 'source "{{common_sh}}"; ensure_posix_root "{{project_root}}" "{{posix_root}}"; confirm_destructive_action "This will roll back the most recent embedded database migration. Continue?"'
|
||||||
cd '{{backend_dir}}' && go run ./cmd/migrate down
|
cd '{{backend_dir}}' && go run ./cmd/migrate down
|
||||||
|
|
||||||
# Reset all embedded database migrations.
|
# Reset all embedded database migrations (confirmation required).
|
||||||
migrate-reset:
|
migrate-reset:
|
||||||
|
bash -c 'source "{{common_sh}}"; ensure_posix_root "{{project_root}}" "{{posix_root}}"; confirm_destructive_action "This will reset all embedded database migrations. Continue?"'
|
||||||
cd '{{backend_dir}}' && go run ./cmd/migrate reset
|
cd '{{backend_dir}}' && go run ./cmd/migrate reset
|
||||||
|
|
||||||
# Reset embedded database migrations and apply them again from scratch.
|
# Reset embedded database migrations and apply them again from scratch (confirmation required).
|
||||||
migrate-rebuild:
|
migrate-rebuild:
|
||||||
|
bash -c 'source "{{common_sh}}"; ensure_posix_root "{{project_root}}" "{{posix_root}}"; confirm_destructive_action "This will reset all embedded database migrations and reapply them from scratch. Continue?"'
|
||||||
cd '{{backend_dir}}' && go run ./cmd/migrate reset && go run ./cmd/migrate up
|
cd '{{backend_dir}}' && go run ./cmd/migrate reset && go run ./cmd/migrate up
|
||||||
|
|
||||||
# Show the embedded database migration status.
|
# Show the embedded database migration status.
|
||||||
migrate-status:
|
migrate-status:
|
||||||
|
bash -c 'source "{{common_sh}}"; ensure_posix_root "{{project_root}}" "{{posix_root}}"'
|
||||||
cd '{{backend_dir}}' && go run ./cmd/migrate status
|
cd '{{backend_dir}}' && go run ./cmd/migrate status
|
||||||
|
|
||||||
# Rebuild the POSIX-to-DB projection from the current POSIX root.
|
# Rebuild the POSIX-to-DB projection from the current POSIX root.
|
||||||
posix-rebuild:
|
posix-rebuild:
|
||||||
|
bash -c 'source "{{common_sh}}"; ensure_posix_root "{{project_root}}" "{{posix_root}}"'
|
||||||
cd '{{backend_dir}}' && go run ./cmd/posix rebuild
|
cd '{{backend_dir}}' && go run ./cmd/posix rebuild
|
||||||
|
|
||||||
# Format backend Go source files.
|
# Format backend Go source files.
|
||||||
fmt:
|
fmt:
|
||||||
|
bash -c 'source "{{common_sh}}"; ensure_posix_root "{{project_root}}" "{{posix_root}}"'
|
||||||
cd '{{backend_dir}}' && gofmt -w ./cmd ./db ./internal
|
cd '{{backend_dir}}' && gofmt -w ./cmd ./db ./internal
|
||||||
|
|||||||
@@ -2,13 +2,17 @@ project_root := justfile_directory()
|
|||||||
local_compose := project_root + "/Docker/docker-compose.local.dev.yaml"
|
local_compose := project_root + "/Docker/docker-compose.local.dev.yaml"
|
||||||
frontend_dir := project_root + "/Frontend"
|
frontend_dir := project_root + "/Frontend"
|
||||||
node_modules_volume := "moku_work_frontend_node_modules"
|
node_modules_volume := "moku_work_frontend_node_modules"
|
||||||
|
common_sh := project_root + "/Commands/Local/scripts/common.sh"
|
||||||
|
posix_root := project_root + "/POSIX"
|
||||||
|
|
||||||
# Recreate the frontend node_modules Docker volume.
|
# Recreate the frontend node_modules Docker volume (confirmation required).
|
||||||
node_modules:
|
node_modules:
|
||||||
|
bash -c 'source "{{common_sh}}"; ensure_posix_root "{{project_root}}" "{{posix_root}}"; confirm_destructive_action "This will recreate the frontend node_modules Docker volume. Continue?"'
|
||||||
docker compose -f '{{local_compose}}' rm -sf frontend >/dev/null 2>&1 || true
|
docker compose -f '{{local_compose}}' rm -sf frontend >/dev/null 2>&1 || true
|
||||||
docker volume rm -f '{{node_modules_volume}}' >/dev/null 2>&1 || true
|
docker volume rm -f '{{node_modules_volume}}' >/dev/null 2>&1 || true
|
||||||
docker compose -f '{{local_compose}}' up -d --remove-orphans --force-recreate frontend
|
docker compose -f '{{local_compose}}' up -d --remove-orphans --force-recreate frontend
|
||||||
|
|
||||||
# Run the frontend TypeScript check.
|
# Run the frontend TypeScript check.
|
||||||
tsc:
|
tsc:
|
||||||
|
bash -c 'source "{{common_sh}}"; ensure_posix_root "{{project_root}}" "{{posix_root}}"'
|
||||||
cd '{{frontend_dir}}' && pnpm typecheck
|
cd '{{frontend_dir}}' && pnpm typecheck
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ start:
|
|||||||
# Alias for the main full local development flow.
|
# Alias for the main full local development flow.
|
||||||
dev: up
|
dev: up
|
||||||
|
|
||||||
# Stop and remove the local development stack.
|
# Stop and remove the local development stack (confirmation required).
|
||||||
down:
|
down:
|
||||||
bash '{{stack_runner}}' down
|
bash '{{stack_runner}}' down
|
||||||
|
|
||||||
@@ -34,6 +34,6 @@ logs:
|
|||||||
restart:
|
restart:
|
||||||
bash '{{stack_runner}}' restart
|
bash '{{stack_runner}}' restart
|
||||||
|
|
||||||
# Stop the local development stack and remove local images, volumes, and backend dev state.
|
# Stop the local development stack and remove local images, volumes, backend dev state, and the local POSIX folder (confirmation required).
|
||||||
clean:
|
clean:
|
||||||
bash '{{stack_runner}}' clean
|
bash '{{stack_runner}}' clean
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ action=${1:-up}
|
|||||||
|
|
||||||
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
||||||
project_root=$(cd -- "$script_dir/../../../.." && pwd)
|
project_root=$(cd -- "$script_dir/../../../.." && pwd)
|
||||||
|
posix_root="$project_root/POSIX"
|
||||||
backend_dir="$project_root/Backend"
|
backend_dir="$project_root/Backend"
|
||||||
backend_bake="$backend_dir/docker-bake.hcl"
|
backend_bake="$backend_dir/docker-bake.hcl"
|
||||||
env_dir="$project_root/Env"
|
env_dir="$project_root/Env"
|
||||||
@@ -15,11 +16,14 @@ runtime_dir="$backend_dir/tmp/dev"
|
|||||||
backend_image="moku/work-backend:dev"
|
backend_image="moku/work-backend:dev"
|
||||||
backend_go_pkg_volume="moku_work_backend_go_pkg"
|
backend_go_pkg_volume="moku_work_backend_go_pkg"
|
||||||
backend_go_build_volume="moku_work_backend_go_build"
|
backend_go_build_volume="moku_work_backend_go_build"
|
||||||
|
local_uid=$(id -u)
|
||||||
|
local_gid=$(id -g)
|
||||||
|
|
||||||
services=(web api worker)
|
services=(web api worker)
|
||||||
|
|
||||||
source "$script_dir/docker.sh"
|
source "$script_dir/docker.sh"
|
||||||
source "$script_dir/env.sh"
|
source "$script_dir/env.sh"
|
||||||
|
source "$project_root/Commands/Local/scripts/common.sh"
|
||||||
|
|
||||||
build_backend() {
|
build_backend() {
|
||||||
cd "$backend_dir"
|
cd "$backend_dir"
|
||||||
@@ -27,20 +31,20 @@ build_backend() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
up_backend() {
|
up_backend() {
|
||||||
docker compose -f "$compose_file" up -d --remove-orphans --force-recreate "${services[@]}"
|
LOCAL_UID="$local_uid" LOCAL_GID="$local_gid" docker compose -f "$compose_file" up -d --remove-orphans --force-recreate "${services[@]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
down_backend() {
|
down_backend() {
|
||||||
docker compose -f "$compose_file" stop "${services[@]}" >/dev/null 2>&1 || true
|
LOCAL_UID="$local_uid" LOCAL_GID="$local_gid" docker compose -f "$compose_file" stop "${services[@]}" >/dev/null 2>&1 || true
|
||||||
docker compose -f "$compose_file" rm -f "${services[@]}" >/dev/null 2>&1 || true
|
LOCAL_UID="$local_uid" LOCAL_GID="$local_gid" docker compose -f "$compose_file" rm -f "${services[@]}" >/dev/null 2>&1 || true
|
||||||
}
|
}
|
||||||
|
|
||||||
restart_backend() {
|
restart_backend() {
|
||||||
docker compose -f "$compose_file" restart "${services[@]}"
|
LOCAL_UID="$local_uid" LOCAL_GID="$local_gid" docker compose -f "$compose_file" restart "${services[@]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
follow_logs() {
|
follow_logs() {
|
||||||
docker compose -f "$compose_file" logs -f "${services[@]}"
|
LOCAL_UID="$local_uid" LOCAL_GID="$local_gid" docker compose -f "$compose_file" logs -f "${services[@]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
clean_runtime() {
|
clean_runtime() {
|
||||||
@@ -50,34 +54,44 @@ clean_runtime() {
|
|||||||
case "$action" in
|
case "$action" in
|
||||||
check)
|
check)
|
||||||
ensure_docker 'docker is required for the local backend dev runtime. Install Docker first.'
|
ensure_docker 'docker is required for the local backend dev runtime. Install Docker first.'
|
||||||
|
ensure_posix_root "$project_root" "$posix_root"
|
||||||
;;
|
;;
|
||||||
build)
|
build)
|
||||||
ensure_docker 'docker is required for the local backend dev runtime. Install Docker first.'
|
ensure_docker 'docker is required for the local backend dev runtime. Install Docker first.'
|
||||||
|
ensure_posix_root "$project_root" "$posix_root"
|
||||||
build_backend
|
build_backend
|
||||||
;;
|
;;
|
||||||
up)
|
up)
|
||||||
ensure_docker 'docker is required for the local backend dev runtime. Install Docker first.'
|
ensure_docker 'docker is required for the local backend dev runtime. Install Docker first.'
|
||||||
ensure_local_env_file "$env_dir"
|
ensure_local_env_file "$env_dir"
|
||||||
|
ensure_posix_root "$project_root" "$posix_root"
|
||||||
up_backend
|
up_backend
|
||||||
|
run_compose_api_migrations "$compose_file" "api"
|
||||||
;;
|
;;
|
||||||
down)
|
down)
|
||||||
ensure_docker 'docker is required for the local backend dev runtime. Install Docker first.'
|
ensure_docker 'docker is required for the local backend dev runtime. Install Docker first.'
|
||||||
ensure_local_env_file "$env_dir"
|
ensure_local_env_file "$env_dir"
|
||||||
|
ensure_posix_root "$project_root" "$posix_root"
|
||||||
|
confirm_destructive_action 'This will stop and remove the local backend dev containers. Continue?'
|
||||||
down_backend
|
down_backend
|
||||||
;;
|
;;
|
||||||
restart)
|
restart)
|
||||||
ensure_docker 'docker is required for the local backend dev runtime. Install Docker first.'
|
ensure_docker 'docker is required for the local backend dev runtime. Install Docker first.'
|
||||||
ensure_local_env_file "$env_dir"
|
ensure_local_env_file "$env_dir"
|
||||||
|
ensure_posix_root "$project_root" "$posix_root"
|
||||||
restart_backend
|
restart_backend
|
||||||
;;
|
;;
|
||||||
logs)
|
logs)
|
||||||
ensure_docker 'docker is required for the local backend dev runtime. Install Docker first.'
|
ensure_docker 'docker is required for the local backend dev runtime. Install Docker first.'
|
||||||
ensure_local_env_file "$env_dir"
|
ensure_local_env_file "$env_dir"
|
||||||
|
ensure_posix_root "$project_root" "$posix_root"
|
||||||
follow_logs
|
follow_logs
|
||||||
;;
|
;;
|
||||||
clean)
|
clean)
|
||||||
ensure_docker 'docker is required for the local backend dev runtime. Install Docker first.'
|
ensure_docker 'docker is required for the local backend dev runtime. Install Docker first.'
|
||||||
ensure_local_env_file "$env_dir"
|
ensure_local_env_file "$env_dir"
|
||||||
|
ensure_posix_root "$project_root" "$posix_root"
|
||||||
|
confirm_destructive_action 'This will remove the local backend dev containers, images, volumes, and runtime state. Continue?'
|
||||||
down_backend
|
down_backend
|
||||||
remove_docker_image_if_present "$backend_image"
|
remove_docker_image_if_present "$backend_image"
|
||||||
remove_docker_volume_if_present "$backend_go_pkg_volume"
|
remove_docker_volume_if_present "$backend_go_pkg_volume"
|
||||||
|
|||||||
@@ -7,12 +7,15 @@ action=${1:-up}
|
|||||||
|
|
||||||
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
||||||
project_root=$(cd -- "$script_dir/../../../.." && pwd)
|
project_root=$(cd -- "$script_dir/../../../.." && pwd)
|
||||||
|
posix_root="$project_root/POSIX"
|
||||||
frontend_dir="$project_root/Frontend"
|
frontend_dir="$project_root/Frontend"
|
||||||
frontend_bake="$frontend_dir/docker-bake.hcl"
|
frontend_bake="$frontend_dir/docker-bake.hcl"
|
||||||
backend_dir="$project_root/Backend"
|
backend_dir="$project_root/Backend"
|
||||||
backend_bake="$backend_dir/docker-bake.hcl"
|
backend_bake="$backend_dir/docker-bake.hcl"
|
||||||
env_dir="$project_root/Env"
|
env_dir="$project_root/Env"
|
||||||
compose_file="$project_root/Docker/docker-compose.local.dev.yaml"
|
compose_file="$project_root/Docker/docker-compose.local.dev.yaml"
|
||||||
|
local_uid=$(id -u)
|
||||||
|
local_gid=$(id -g)
|
||||||
frontend_image="moku/work-frontend:dev"
|
frontend_image="moku/work-frontend:dev"
|
||||||
backend_image="moku/work-backend:dev"
|
backend_image="moku/work-backend:dev"
|
||||||
frontend_volume="moku_work_frontend_node_modules"
|
frontend_volume="moku_work_frontend_node_modules"
|
||||||
@@ -22,6 +25,7 @@ backend_runtime_dir="$backend_dir/tmp/dev"
|
|||||||
|
|
||||||
source "$script_dir/docker.sh"
|
source "$script_dir/docker.sh"
|
||||||
source "$script_dir/env.sh"
|
source "$script_dir/env.sh"
|
||||||
|
source "$project_root/Commands/Local/scripts/common.sh"
|
||||||
|
|
||||||
build_frontend() {
|
build_frontend() {
|
||||||
cd "$frontend_dir"
|
cd "$frontend_dir"
|
||||||
@@ -39,19 +43,19 @@ build_images() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
up_stack() {
|
up_stack() {
|
||||||
docker compose -f "$compose_file" up -d --remove-orphans --force-recreate
|
LOCAL_UID="$local_uid" LOCAL_GID="$local_gid" docker compose -f "$compose_file" up -d --remove-orphans --force-recreate
|
||||||
}
|
}
|
||||||
|
|
||||||
down_stack() {
|
down_stack() {
|
||||||
docker compose -f "$compose_file" down --remove-orphans --volumes
|
LOCAL_UID="$local_uid" LOCAL_GID="$local_gid" docker compose -f "$compose_file" down --remove-orphans --volumes
|
||||||
}
|
}
|
||||||
|
|
||||||
follow_logs() {
|
follow_logs() {
|
||||||
docker compose -f "$compose_file" logs -f
|
LOCAL_UID="$local_uid" LOCAL_GID="$local_gid" docker compose -f "$compose_file" logs -f
|
||||||
}
|
}
|
||||||
|
|
||||||
clean_stack() {
|
clean_stack() {
|
||||||
docker compose -f "$compose_file" down --remove-orphans --volumes >/dev/null 2>&1 || true
|
LOCAL_UID="$local_uid" LOCAL_GID="$local_gid" docker compose -f "$compose_file" down --remove-orphans --volumes >/dev/null 2>&1 || true
|
||||||
remove_docker_image_if_present "$frontend_image"
|
remove_docker_image_if_present "$frontend_image"
|
||||||
remove_docker_image_if_present "$backend_image"
|
remove_docker_image_if_present "$backend_image"
|
||||||
remove_docker_volume_if_present "$frontend_volume"
|
remove_docker_volume_if_present "$frontend_volume"
|
||||||
@@ -63,37 +67,47 @@ clean_stack() {
|
|||||||
start_stack() {
|
start_stack() {
|
||||||
build_images
|
build_images
|
||||||
up_stack
|
up_stack
|
||||||
|
run_compose_api_migrations "$compose_file" "api"
|
||||||
}
|
}
|
||||||
|
|
||||||
case "$action" in
|
case "$action" in
|
||||||
build)
|
build)
|
||||||
ensure_docker 'docker is required for the local development stack. Install Docker first.'
|
ensure_docker 'docker is required for the local development stack. Install Docker first.'
|
||||||
|
ensure_posix_root "$project_root" "$posix_root"
|
||||||
build_images
|
build_images
|
||||||
;;
|
;;
|
||||||
up|start|rebuild)
|
up|start|rebuild)
|
||||||
ensure_docker 'docker is required for the local development stack. Install Docker first.'
|
ensure_docker 'docker is required for the local development stack. Install Docker first.'
|
||||||
ensure_local_env_file "$env_dir"
|
ensure_local_env_file "$env_dir"
|
||||||
|
ensure_posix_root "$project_root" "$posix_root"
|
||||||
start_stack
|
start_stack
|
||||||
;;
|
;;
|
||||||
down)
|
down)
|
||||||
ensure_docker 'docker is required for the local development stack. Install Docker first.'
|
ensure_docker 'docker is required for the local development stack. Install Docker first.'
|
||||||
ensure_local_env_file "$env_dir"
|
ensure_local_env_file "$env_dir"
|
||||||
|
ensure_posix_root "$project_root" "$posix_root"
|
||||||
|
confirm_destructive_action 'This will stop the local development stack and remove its containers and volumes. Continue?'
|
||||||
down_stack
|
down_stack
|
||||||
;;
|
;;
|
||||||
restart)
|
restart)
|
||||||
ensure_docker 'docker is required for the local development stack. Install Docker first.'
|
ensure_docker 'docker is required for the local development stack. Install Docker first.'
|
||||||
ensure_local_env_file "$env_dir"
|
ensure_local_env_file "$env_dir"
|
||||||
docker compose -f "$compose_file" restart
|
ensure_posix_root "$project_root" "$posix_root"
|
||||||
|
LOCAL_UID="$local_uid" LOCAL_GID="$local_gid" docker compose -f "$compose_file" restart
|
||||||
;;
|
;;
|
||||||
logs)
|
logs)
|
||||||
ensure_docker 'docker is required for the local development stack. Install Docker first.'
|
ensure_docker 'docker is required for the local development stack. Install Docker first.'
|
||||||
ensure_local_env_file "$env_dir"
|
ensure_local_env_file "$env_dir"
|
||||||
|
ensure_posix_root "$project_root" "$posix_root"
|
||||||
follow_logs
|
follow_logs
|
||||||
;;
|
;;
|
||||||
clean)
|
clean)
|
||||||
ensure_docker 'docker is required for the local development stack. Install Docker first.'
|
ensure_docker 'docker is required for the local development stack. Install Docker first.'
|
||||||
ensure_local_env_file "$env_dir"
|
ensure_local_env_file "$env_dir"
|
||||||
|
ensure_posix_root "$project_root" "$posix_root"
|
||||||
|
confirm_destructive_action 'This will remove the local development stack, local images, volumes, backend dev state, and the local POSIX folder. Continue?'
|
||||||
clean_stack
|
clean_stack
|
||||||
|
rm -rf "$posix_root"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
printf 'Unsupported dev stack action: %s\n' "$action" >&2
|
printf 'Unsupported dev stack action: %s\n' "$action" >&2
|
||||||
|
|||||||
@@ -5,40 +5,49 @@ local_compose := project_root + "/Docker/docker-compose.local.prod.yaml"
|
|||||||
proxy_image := "moku/work-proxy:local-prod"
|
proxy_image := "moku/work-proxy:local-prod"
|
||||||
backend_api_image := "moku/work-backend:local-prod-api"
|
backend_api_image := "moku/work-backend:local-prod-api"
|
||||||
backend_worker_image := "moku/work-backend:local-prod-worker"
|
backend_worker_image := "moku/work-backend:local-prod-worker"
|
||||||
|
common_sh := project_root + "/Commands/Local/scripts/common.sh"
|
||||||
|
posix_root := project_root + "/POSIX"
|
||||||
|
|
||||||
# Build the local production proxy image locally.
|
# Build the local production proxy image locally.
|
||||||
build:
|
build:
|
||||||
|
bash -c 'source "{{common_sh}}"; ensure_posix_root "{{project_root}}" "{{posix_root}}"'
|
||||||
cd '{{project_root}}' && docker buildx bake -f '{{proxy_bake}}' prod
|
cd '{{project_root}}' && docker buildx bake -f '{{proxy_bake}}' prod
|
||||||
cd '{{project_root}}' && docker buildx bake -f '{{backend_bake}}' prod-api prod-worker
|
cd '{{project_root}}' && docker buildx bake -f '{{backend_bake}}' prod-api prod-worker
|
||||||
|
|
||||||
# Start the local production stack in the background using the current image.
|
# Start the local production stack in the background using the current image.
|
||||||
up:
|
up:
|
||||||
docker compose -f '{{local_compose}}' up -d --remove-orphans --force-recreate
|
bash -c 'source "{{common_sh}}"; ensure_posix_root "{{project_root}}" "{{posix_root}}"'
|
||||||
|
LOCAL_UID="$$(id -u)" LOCAL_GID="$$(id -g)" docker compose -f '{{local_compose}}' up -d --remove-orphans --force-recreate
|
||||||
|
|
||||||
# Build first, then start the local production stack in the background.
|
# Build first, then start the local production stack in the background.
|
||||||
start: build up
|
start: build up
|
||||||
|
|
||||||
# Rebuild the local production proxy image locally.
|
# Rebuild the local production proxy image locally.
|
||||||
rebuild:
|
rebuild:
|
||||||
|
bash -c 'source "{{common_sh}}"; ensure_posix_root "{{project_root}}" "{{posix_root}}"'
|
||||||
cd '{{project_root}}' && docker buildx bake -f '{{proxy_bake}}' --set '*.no-cache=true' prod
|
cd '{{project_root}}' && docker buildx bake -f '{{proxy_bake}}' --set '*.no-cache=true' prod
|
||||||
cd '{{project_root}}' && docker buildx bake -f '{{backend_bake}}' --set '*.no-cache=true' prod-api prod-worker
|
cd '{{project_root}}' && docker buildx bake -f '{{backend_bake}}' --set '*.no-cache=true' prod-api prod-worker
|
||||||
docker compose -f '{{local_compose}}' up -d --remove-orphans --force-recreate
|
LOCAL_UID="$$(id -u)" LOCAL_GID="$$(id -g)" docker compose -f '{{local_compose}}' up -d --remove-orphans --force-recreate
|
||||||
|
|
||||||
# Stop and remove the local production stack.
|
# Stop and remove the local production stack (confirmation required).
|
||||||
down:
|
down:
|
||||||
docker compose -f '{{local_compose}}' down --remove-orphans --volumes
|
bash -c 'source "{{common_sh}}"; ensure_posix_root "{{project_root}}" "{{posix_root}}"; confirm_destructive_action "This will stop the local production stack and remove its containers and volumes. Continue?"'
|
||||||
|
LOCAL_UID="$$(id -u)" LOCAL_GID="$$(id -g)" docker compose -f '{{local_compose}}' down --remove-orphans --volumes
|
||||||
|
|
||||||
# Follow logs for the local production stack.
|
# Follow logs for the local production stack.
|
||||||
logs:
|
logs:
|
||||||
docker compose -f '{{local_compose}}' logs -f
|
bash -c 'source "{{common_sh}}"; ensure_posix_root "{{project_root}}" "{{posix_root}}"'
|
||||||
|
LOCAL_UID="$$(id -u)" LOCAL_GID="$$(id -g)" docker compose -f '{{local_compose}}' logs -f
|
||||||
|
|
||||||
# Restart the local production stack.
|
# Restart the local production stack.
|
||||||
restart:
|
restart:
|
||||||
docker compose -f '{{local_compose}}' restart
|
bash -c 'source "{{common_sh}}"; ensure_posix_root "{{project_root}}" "{{posix_root}}"'
|
||||||
|
LOCAL_UID="$$(id -u)" LOCAL_GID="$$(id -g)" docker compose -f '{{local_compose}}' restart
|
||||||
|
|
||||||
# Stop the local production stack and remove local images.
|
# Stop the local production stack and remove local images (confirmation required).
|
||||||
clean:
|
clean:
|
||||||
docker compose -f '{{local_compose}}' down --remove-orphans --volumes
|
bash -c 'source "{{common_sh}}"; ensure_posix_root "{{project_root}}" "{{posix_root}}"; confirm_destructive_action "This will remove the local production stack, its volumes, and the local production images. Continue?"'
|
||||||
|
LOCAL_UID="$$(id -u)" LOCAL_GID="$$(id -g)" docker compose -f '{{local_compose}}' down --remove-orphans --volumes
|
||||||
docker image rm -f '{{proxy_image}}' >/dev/null 2>&1 || true
|
docker image rm -f '{{proxy_image}}' >/dev/null 2>&1 || true
|
||||||
docker image rm -f '{{backend_api_image}}' >/dev/null 2>&1 || true
|
docker image rm -f '{{backend_api_image}}' >/dev/null 2>&1 || true
|
||||||
docker image rm -f '{{backend_worker_image}}' >/dev/null 2>&1 || true
|
docker image rm -f '{{backend_worker_image}}' >/dev/null 2>&1 || true
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ensure_posix_root() {
|
||||||
|
local project_root=${1:?project root is required}
|
||||||
|
local posix_root=${2:-"$project_root/POSIX"}
|
||||||
|
|
||||||
|
mkdir -p "$posix_root"
|
||||||
|
}
|
||||||
|
|
||||||
|
confirm_destructive_action() {
|
||||||
|
local prompt=${1:-Are you sure you want to continue?}
|
||||||
|
local response_input=""
|
||||||
|
|
||||||
|
if [[ "${JUST_YES:-0}" == "1" ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -t 0 ]]; then
|
||||||
|
printf '%s [y/N] ' "$prompt"
|
||||||
|
IFS= read -r response_input
|
||||||
|
elif [[ -r /dev/tty ]]; then
|
||||||
|
printf '%s [y/N] ' "$prompt" > /dev/tty
|
||||||
|
IFS= read -r response_input < /dev/tty
|
||||||
|
else
|
||||||
|
printf 'Refusing destructive action without interactive confirmation. Re-run with JUST_YES=1 to continue.\n' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$response_input" in
|
||||||
|
y|Y|yes|YES|Yes)
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
printf 'Aborted.\n' >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
run_compose_api_migrations() {
|
||||||
|
local compose_file=${1:?compose file is required}
|
||||||
|
local service_name=${2:-api}
|
||||||
|
local max_attempts=${3:-20}
|
||||||
|
local sleep_seconds=${4:-2}
|
||||||
|
local attempt=1
|
||||||
|
local output=""
|
||||||
|
|
||||||
|
while (( attempt <= max_attempts )); do
|
||||||
|
if output=$(docker compose -f "$compose_file" exec -T "$service_name" sh -lc 'go run ./cmd/migrate up' 2>&1); then
|
||||||
|
printf '%s\n' "$output"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (( attempt == max_attempts )); then
|
||||||
|
printf 'Failed to apply database migrations automatically after %d attempts.\n' "$max_attempts" >&2
|
||||||
|
printf '%s\n' "$output" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep "$sleep_seconds"
|
||||||
|
attempt=$((attempt + 1))
|
||||||
|
done
|
||||||
|
}
|
||||||
@@ -1,12 +1,16 @@
|
|||||||
x-backend-service: &backend-service
|
x-backend-service: &backend-service
|
||||||
image: moku/work-backend:dev
|
image: moku/work-backend:dev
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
user: "${LOCAL_UID:-1000}:${LOCAL_GID:-1000}"
|
||||||
env_file:
|
env_file:
|
||||||
- ../Env/.env.local
|
- ../Env/.env.local
|
||||||
environment:
|
environment:
|
||||||
DATABASE_URL: postgres://moku:moku_dev_password@postgres:5432/moku?sslmode=disable
|
DATABASE_URL: postgres://moku:moku_dev_password@postgres:5432/moku?sslmode=disable
|
||||||
VALKEY_URL: redis://valkey:6379/0
|
VALKEY_URL: redis://valkey:6379/0
|
||||||
POSIX_ROOT: /posix
|
POSIX_ROOT: /posix
|
||||||
|
HOME: /tmp/home
|
||||||
|
GOMODCACHE: /tmp/go/pkg/mod
|
||||||
|
GOCACHE: /tmp/go-build
|
||||||
depends_on:
|
depends_on:
|
||||||
postgres:
|
postgres:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
@@ -15,8 +19,8 @@ x-backend-service: &backend-service
|
|||||||
volumes:
|
volumes:
|
||||||
- ../Backend:/app
|
- ../Backend:/app
|
||||||
- ../POSIX:/posix
|
- ../POSIX:/posix
|
||||||
- moku_work_backend_go_pkg:/go/pkg/mod
|
- moku_work_backend_go_pkg:/tmp/go/pkg/mod
|
||||||
- moku_work_backend_go_build:/root/.cache/go-build
|
- moku_work_backend_go_build:/tmp/go-build
|
||||||
|
|
||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
x-backend-service: &backend-service
|
x-backend-service: &backend-service
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
user: "${LOCAL_UID:-1000}:${LOCAL_GID:-1000}"
|
||||||
env_file:
|
env_file:
|
||||||
- ../Env/.env.local
|
- ../Env/.env.local
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
Reference in New Issue
Block a user