Merge branch 'factory-fix' into dev
Deploy DeepDrftAPI / Build, Publish & Bundle (push) Successful in 2m28s
Package install tarball / package (push) Successful in 6s
Deploy DeepDrftAPI / Deploy (push) Successful in 1m35s

This commit is contained in:
daniel-c-harvey
2026-06-04 14:16:35 -04:00
6 changed files with 16 additions and 60 deletions
-8
View File
@@ -45,14 +45,6 @@ jobs:
--no-build \
-o DeepDrftAPI/publish
# DeepDrftContextFactory reads environment/connections.json at design time.
# Write a parseable dummy so the factory does not throw during bundle construction.
# The bundle only needs the provider type, not a live database connection.
- name: Write dummy connections file for EF bundle
run: |
mkdir -p DeepDrftAPI/environment
echo '{"ConnectionStrings":{"DefaultConnection":"Host=localhost;Database=dummy;Username=dummy","Auth":"Host=localhost;Database=dummy;Username=dummy"}}' > DeepDrftAPI/environment/connections.json
# EF bundle: self-contained binary that applies DeepDrftContext migrations on the host
# without the .NET SDK. AuthBlocks' Identity DB is NOT covered here — it self-migrates
# via UseAuthBlocksStartupAsync() on first boot.
+15 -16
View File
@@ -1,5 +1,6 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using NetBlocks.Utilities.Environment;
namespace DeepDrftData.Data;
@@ -7,23 +8,21 @@ public class DeepDrftContextFactory : IDesignTimeDbContextFactory<DeepDrftContex
{
public DeepDrftContext CreateDbContext(string[] args)
{
// Load the real connection string from environment/connections.json — the same
// file DeepDrftPublic's Program.cs loads via CredentialTools. When EF tools run with
// --startup-project DeepDrftPublic, the working directory resolves there, so this
// relative path works without any env var configuration.
const string relPath = "environment/connections.json";
if (!File.Exists(relPath))
throw new FileNotFoundException(
$"'{relPath}' not found. Run EF commands with --startup-project DeepDrftPublic " +
$"from the solution root (current dir: {Directory.GetCurrentDirectory()}).", relPath);
var path = CredentialTools.ResolvePath("connections", "environment/connections.json");
using var doc = System.Text.Json.JsonDocument.Parse(File.ReadAllText(relPath));
var connectionString = doc.RootElement
.GetProperty("ConnectionStrings")
.GetProperty("DefaultConnection")
.GetString()
?? throw new InvalidOperationException(
"ConnectionStrings:DefaultConnection not found in environment/connections.json");
string? connectionString = null;
if (File.Exists(path))
{
using var doc = System.Text.Json.JsonDocument.Parse(File.ReadAllText(path));
connectionString = doc.RootElement
.GetProperty("ConnectionStrings")
.GetProperty("DefaultConnection")
.GetString();
}
// Fall back to a design-time dummy — the bundle only needs the provider/schema,
// not a live connection. This removes the requirement to write a dummy file in CI.
connectionString ??= "Host=localhost;Database=deepdrft-design-time;Username=dummy";
var optionsBuilder = new DbContextOptionsBuilder<DeepDrftContext>();
optionsBuilder.UseNpgsql(connectionString);
+1
View File
@@ -18,6 +18,7 @@
</PackageReference>
<!-- Npgsql 10.0.1 requires Microsoft.EntityFrameworkCore >= 10.0.4; keep in sync -->
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.1" />
<PackageReference Include="Cerebellum.NetBlocks" Version="10.3.30" />
<PackageReference Include="Cerebellum.BlazorBlocks.Data" Version="10.3.30" />
<PackageReference Include="Cerebellum.BlazorBlocks.Data.Postgres" Version="10.3.30" />
</ItemGroup>
-15
View File
@@ -5,9 +5,6 @@
# Expects in ${APP_HOME}/staging/:
# deepdrft-manager.tar.gz -- published self-contained linux-x64 binary tree
#
# DeepDrftManager reads its API URL and API key credential from environment/api.json at startup
# (populated by setup-step10-creds.sh). The env-file copy block below keeps it current.
#
# Paths are derived at runtime — no hardcoded usernames or home dirs.
# APP_HOME comes from $HOME (sshd sets this for the app user).
@@ -36,18 +33,6 @@ rm -f "${STAGING}/${ARCHIVE}"
echo "[deploy-manager] archive extracted"
# ── Apply environment files (host-managed, not in archive) ────────────────
if [[ -d "${APPROOT}/environment" ]]; then
shopt -s nullglob
env_files=("${APPROOT}/environment/"*)
shopt -u nullglob
if [[ ${#env_files[@]} -gt 0 ]]; then
mkdir -p "${APPROOT}/bin/environment"
cp "${env_files[@]}" "${APPROOT}/bin/environment/"
echo "[deploy-manager] environment files applied"
fi
fi
# ── Enable and restart service ─────────────────────────────────────────────
systemctl --user enable deepdrftmanager.service
systemctl --user restart deepdrftmanager.service
-15
View File
@@ -5,9 +5,6 @@
# Expects in ${APP_HOME}/staging/:
# deepdrft-public.tar.gz -- published self-contained linux-x64 binary tree
#
# DeepDrftPublic reads its API URL credential from environment/api.json at startup
# (populated by setup-step10-creds.sh). The env-file copy block below keeps it current.
#
# Paths are derived at runtime — no hardcoded usernames or home dirs.
# APP_HOME comes from $HOME (sshd sets this for the app user).
@@ -36,18 +33,6 @@ rm -f "${STAGING}/${ARCHIVE}"
echo "[deploy-public] archive extracted"
# ── Apply environment files (host-managed, not in archive) ────────────────
if [[ -d "${APPROOT}/environment" ]]; then
shopt -s nullglob
env_files=("${APPROOT}/environment/"*)
shopt -u nullglob
if [[ ${#env_files[@]} -gt 0 ]]; then
mkdir -p "${APPROOT}/bin/environment"
cp "${env_files[@]}" "${APPROOT}/bin/environment/"
echo "[deploy-public] environment files applied"
fi
fi
# ── Enable and restart service ─────────────────────────────────────────────
systemctl --user enable deepdrftpublic.service
systemctl --user restart deepdrftpublic.service
-6
View File
@@ -92,7 +92,6 @@ need_cred() {
if need_cred "filedatabase"; then
write_cred "filedatabase" \
"{\"FileDatabaseSettings\":{\"VaultPath\":\"${APP_HOME}/api/deepdrft/vaults\"}}"
cp "${CREDDIR}/filedatabase.json" "${APP_HOME}/api/deepdrft/environment/filedatabase.json"
else
echo "[setup-step10-creds] filedatabase.json already exists, skipping"
fi
@@ -111,7 +110,6 @@ if need_cred "apikey"; then
unset API_KEY_INPUT
write_cred "apikey" \
"{\"ApiKeySettings\":{\"ApiKey\":\"$(json_escape "${API_KEY}")\"}}"
cp "${CREDDIR}/apikey.json" "${APP_HOME}/api/deepdrft/environment/apikey.json"
else
echo "[setup-step10-creds] apikey.json already exists, skipping"
# Still need the value for api-manager.json if that's also being written.
@@ -152,7 +150,6 @@ if need_cred "connections"; then
AUTH_CONN="Host=localhost;Database=${DB_AUTH};Username=${PG_ROLE};Password=$(json_escape "${PG_PASSWORD}")"
write_cred "connections" \
"{\"ConnectionStrings\":{\"DefaultConnection\":\"${META_CONN}\",\"Auth\":\"${AUTH_CONN}\"}}"
cp "${CREDDIR}/connections.json" "${APP_HOME}/api/deepdrft/environment/connections.json"
unset PG_PASSWORD META_CONN AUTH_CONN
else
echo "[setup-step10-creds] connections.json already exists, skipping"
@@ -207,7 +204,6 @@ if need_cred "authblocks"; then
{"AuthBlocks":{"Jwt":{"Secret":"$(json_escape "${JWT_SECRET}")","Issuer":"$(json_escape "${JWT_ISSUER}")","Audience":"$(json_escape "${JWT_AUDIENCE}")"},"Email":{"Host":"$(json_escape "${EMAIL_HOST}")","Token":"$(json_escape "${EMAIL_TOKEN}")"},"Admin":{"UserName":"$(json_escape "${ADMIN_USERNAME}")","Email":"$(json_escape "${ADMIN_EMAIL}")","Password":"$(json_escape "${ADMIN_PASSWORD}")"},"SupportEmail":"$(json_escape "${SUPPORT_EMAIL}")"}}
JSON
)"
cp "${CREDDIR}/authblocks.json" "${APP_HOME}/api/deepdrft/environment/authblocks.json"
unset JWT_SECRET JWT_ISSUER JWT_AUDIENCE EMAIL_HOST EMAIL_TOKEN
unset ADMIN_USERNAME ADMIN_EMAIL ADMIN_PASSWORD SUPPORT_EMAIL
else
@@ -218,7 +214,6 @@ fi
if need_cred "api-public"; then
write_cred "api-public" \
"{\"Api\":{\"ContentApiUrl\":\"http://localhost:${PORT_API:-5002}\"}}"
cp "${CREDDIR}/api-public.json" "${APP_HOME}/public/environment/api.json"
else
echo "[setup-step10-creds] api-public.json already exists, skipping"
fi
@@ -232,7 +227,6 @@ if need_cred "api-manager"; then
fi
write_cred "api-manager" \
"{\"Api\":{\"ContentApiUrl\":\"http://localhost:${PORT_API:-5002}\",\"ContentApiKey\":\"$(json_escape "${API_KEY}")\"}}"
cp "${CREDDIR}/api-manager.json" "${APP_HOME}/manager/environment/api.json"
unset API_KEY
else
echo "[setup-step10-creds] api-manager.json already exists, skipping"