qa-environment-aspire (#2)
Reviewed-on: #2 Co-authored-by: James Wampler <james@wamp.dev> Co-committed-by: James Wampler <james@wamp.dev>
This commit was merged in pull request #2.
This commit is contained in:
18
scripts/ci/build.sh
Executable file
18
scripts/ci/build.sh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
# Compiles the API (and its dependents) and builds the admin SPA.
|
||||
# Acts as the compile gate before tests/image builds run. TreatWarningsAsErrors
|
||||
# is enabled across the solution, so this also fails on any compiler warning.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "${BASH_SOURCE[0]}")" && source ./lib.sh
|
||||
cd "$CI_ROOT"
|
||||
|
||||
log "Restoring and publishing MicCheck.Api (Release)"
|
||||
dotnet publish src/api/MicCheck.Api/MicCheck.Api.csproj -c Release
|
||||
|
||||
log "Installing admin dependencies (npm ci)"
|
||||
npm --prefix src/admin ci
|
||||
|
||||
log "Building admin SPA (vite build)"
|
||||
npm --prefix src/admin run build
|
||||
|
||||
log "build.sh complete"
|
||||
37
scripts/ci/deploy-qa.sh
Executable file
37
scripts/ci/deploy-qa.sh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploys the freshly-pushed :qa images to the dedicated, network-isolated QA
|
||||
# stack and recreates the miccheck database in an empty state. Safe/idempotent
|
||||
# to re-run: `down -v` removes the Postgres data volume, and the API's own
|
||||
# startup logic (EF Core migrations + idempotent dev seeding) rebuilds it.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "${BASH_SOURCE[0]}")" && source ./lib.sh
|
||||
cd "$CI_ROOT"
|
||||
image_names
|
||||
registry_login
|
||||
|
||||
export API_IMAGE ADMIN_IMAGE
|
||||
export JWT_SECRET_KEY="${JWT_SECRET_KEY:?JWT_SECRET_KEY env var is required}"
|
||||
export QA_ADMIN_PORT="${QA_ADMIN_PORT:-3001}"
|
||||
|
||||
COMPOSE="docker compose -p miccheck-qa -f deploy/qa/docker-compose.qa.yml"
|
||||
|
||||
log "Pulling latest :qa images"
|
||||
$COMPOSE pull
|
||||
|
||||
log "Tearing down existing QA stack and wiping the database volume"
|
||||
$COMPOSE down -v
|
||||
|
||||
log "Starting QA stack"
|
||||
$COMPOSE up -d
|
||||
|
||||
log "Waiting for API health check via admin proxy on port $QA_ADMIN_PORT"
|
||||
attempts=30
|
||||
until curl -fsS "http://localhost:${QA_ADMIN_PORT}/api/v1/health" >/dev/null 2>&1; do
|
||||
attempts=$((attempts - 1))
|
||||
if [[ "$attempts" -le 0 ]]; then
|
||||
fail "QA stack did not become healthy in time"
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
log "QA environment deployed and healthy at http://localhost:${QA_ADMIN_PORT}"
|
||||
23
scripts/ci/docker-build.sh
Executable file
23
scripts/ci/docker-build.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
# Builds self-contained CI images for the API and admin apps and tags them
|
||||
# with both the current git sha and "qa" (the tag the QA compose stack pulls).
|
||||
set -euo pipefail
|
||||
cd "$(dirname "${BASH_SOURCE[0]}")" && source ./lib.sh
|
||||
cd "$CI_ROOT"
|
||||
image_names
|
||||
|
||||
log "Building $API_IMAGE:$GIT_SHA / :qa"
|
||||
docker build \
|
||||
-f src/api/MicCheck.Api/Dockerfile.ci \
|
||||
-t "$API_IMAGE:$GIT_SHA" \
|
||||
-t "$API_IMAGE:qa" \
|
||||
.
|
||||
|
||||
log "Building $ADMIN_IMAGE:$GIT_SHA / :qa"
|
||||
docker build \
|
||||
-f src/admin/Dockerfile.ci \
|
||||
-t "$ADMIN_IMAGE:$GIT_SHA" \
|
||||
-t "$ADMIN_IMAGE:qa" \
|
||||
src/admin
|
||||
|
||||
log "docker-build.sh complete"
|
||||
17
scripts/ci/docker-push.sh
Executable file
17
scripts/ci/docker-push.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
# Pushes the images built by docker-build.sh (git-sha and qa tags) to the
|
||||
# Gitea container registry.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "${BASH_SOURCE[0]}")" && source ./lib.sh
|
||||
cd "$CI_ROOT"
|
||||
image_names
|
||||
registry_login
|
||||
|
||||
for tag in "$GIT_SHA" qa; do
|
||||
log "Pushing $API_IMAGE:$tag"
|
||||
docker push "$API_IMAGE:$tag"
|
||||
log "Pushing $ADMIN_IMAGE:$tag"
|
||||
docker push "$ADMIN_IMAGE:$tag"
|
||||
done
|
||||
|
||||
log "docker-push.sh complete"
|
||||
46
scripts/ci/lib.sh
Executable file
46
scripts/ci/lib.sh
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env bash
|
||||
# Shared helpers for scripts/ci/*.sh.
|
||||
# Every script in this directory is meant to run identically in CI and on a
|
||||
# developer's machine - no Gitea/GitHub-specific built-in actions, just bash.
|
||||
set -euo pipefail
|
||||
|
||||
log() {
|
||||
echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] $*"
|
||||
}
|
||||
|
||||
fail() {
|
||||
echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] ERROR: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Repo root, regardless of caller's cwd.
|
||||
CI_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
|
||||
# Registry configuration. All values come from the environment (CI secrets or
|
||||
# a developer's shell) - nothing is hardcoded, per project convention.
|
||||
REGISTRY="${REGISTRY:-}"
|
||||
REGISTRY_OWNER="${REGISTRY_OWNER:-}"
|
||||
REGISTRY_USER="${REGISTRY_USER:-}"
|
||||
REGISTRY_TOKEN="${REGISTRY_TOKEN:-}"
|
||||
|
||||
GIT_SHA="$(git -C "$CI_ROOT" rev-parse --short HEAD)"
|
||||
|
||||
require_registry_vars() {
|
||||
[[ -n "$REGISTRY" ]] || fail "REGISTRY env var is required (e.g. gitea.example.com)"
|
||||
[[ -n "$REGISTRY_OWNER" ]] || fail "REGISTRY_OWNER env var is required (e.g. your gitea org/user)"
|
||||
}
|
||||
|
||||
# Populates API_IMAGE / ADMIN_IMAGE, e.g. gitea.example.com/james/miccheck-api
|
||||
image_names() {
|
||||
require_registry_vars
|
||||
API_IMAGE="$REGISTRY/$REGISTRY_OWNER/miccheck-api"
|
||||
ADMIN_IMAGE="$REGISTRY/$REGISTRY_OWNER/miccheck-admin"
|
||||
}
|
||||
|
||||
registry_login() {
|
||||
require_registry_vars
|
||||
[[ -n "$REGISTRY_USER" ]] || fail "REGISTRY_USER env var is required to push images"
|
||||
[[ -n "$REGISTRY_TOKEN" ]] || fail "REGISTRY_TOKEN env var is required to push images"
|
||||
log "Logging in to $REGISTRY as $REGISTRY_USER"
|
||||
echo "$REGISTRY_TOKEN" | docker login "$REGISTRY" -u "$REGISTRY_USER" --password-stdin
|
||||
}
|
||||
23
scripts/ci/prepush.sh
Executable file
23
scripts/ci/prepush.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
# Husky pre-push hook body. Compiles everything and runs the fast test suites
|
||||
# (no Docker, no registry) so broken code/tests never leave the workstation.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "${BASH_SOURCE[0]}")" && source ./lib.sh
|
||||
cd "$CI_ROOT"
|
||||
|
||||
log "Building full solution (Debug)"
|
||||
dotnet build MicCheck.slnx -c Debug
|
||||
|
||||
log "Running MicCheck.Api.Tests.Unit"
|
||||
dotnet test tests/api/MicCheck.Api.Tests.Unit/MicCheck.Api.Tests.Unit.csproj -c Debug
|
||||
|
||||
log "Installing admin dependencies (npm ci)"
|
||||
npm --prefix src/admin ci
|
||||
|
||||
log "Running admin Jest tests"
|
||||
npm --prefix src/admin test
|
||||
|
||||
log "Building admin SPA (vite build)"
|
||||
npm --prefix src/admin run build
|
||||
|
||||
log "prepush.sh complete - ok to push"
|
||||
15
scripts/ci/test.sh
Executable file
15
scripts/ci/test.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
# Runs the fast test suites: .NET unit tests (EF InMemory, no DB/Docker needed)
|
||||
# and the admin Jest suite. Integration tests are intentionally excluded here -
|
||||
# they require a live API + Postgres (see readme in the Integration test project).
|
||||
set -euo pipefail
|
||||
cd "$(dirname "${BASH_SOURCE[0]}")" && source ./lib.sh
|
||||
cd "$CI_ROOT"
|
||||
|
||||
log "Running MicCheck.Api.Tests.Unit"
|
||||
dotnet test tests/api/MicCheck.Api.Tests.Unit/MicCheck.Api.Tests.Unit.csproj -c Release --logger trx
|
||||
|
||||
log "Running admin Jest tests"
|
||||
npm --prefix src/admin test
|
||||
|
||||
log "test.sh complete"
|
||||
Reference in New Issue
Block a user