Merge branch 'factory-fix' into dev
This commit is contained in:
@@ -45,14 +45,6 @@ jobs:
|
|||||||
--no-build \
|
--no-build \
|
||||||
-o DeepDrftAPI/publish
|
-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
|
# 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
|
# without the .NET SDK. AuthBlocks' Identity DB is NOT covered here — it self-migrates
|
||||||
# via UseAuthBlocksStartupAsync() on first boot.
|
# via UseAuthBlocksStartupAsync() on first boot.
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Design;
|
using Microsoft.EntityFrameworkCore.Design;
|
||||||
|
using NetBlocks.Utilities.Environment;
|
||||||
|
|
||||||
namespace DeepDrftData.Data;
|
namespace DeepDrftData.Data;
|
||||||
|
|
||||||
@@ -7,23 +8,21 @@ public class DeepDrftContextFactory : IDesignTimeDbContextFactory<DeepDrftContex
|
|||||||
{
|
{
|
||||||
public DeepDrftContext CreateDbContext(string[] args)
|
public DeepDrftContext CreateDbContext(string[] args)
|
||||||
{
|
{
|
||||||
// Load the real connection string from environment/connections.json — the same
|
var path = CredentialTools.ResolvePath("connections", "environment/connections.json");
|
||||||
// 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);
|
|
||||||
|
|
||||||
using var doc = System.Text.Json.JsonDocument.Parse(File.ReadAllText(relPath));
|
string? connectionString = null;
|
||||||
var connectionString = doc.RootElement
|
if (File.Exists(path))
|
||||||
.GetProperty("ConnectionStrings")
|
{
|
||||||
.GetProperty("DefaultConnection")
|
using var doc = System.Text.Json.JsonDocument.Parse(File.ReadAllText(path));
|
||||||
.GetString()
|
connectionString = doc.RootElement
|
||||||
?? throw new InvalidOperationException(
|
.GetProperty("ConnectionStrings")
|
||||||
"ConnectionStrings:DefaultConnection not found in environment/connections.json");
|
.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>();
|
var optionsBuilder = new DbContextOptionsBuilder<DeepDrftContext>();
|
||||||
optionsBuilder.UseNpgsql(connectionString);
|
optionsBuilder.UseNpgsql(connectionString);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
</PackageReference>
|
</PackageReference>
|
||||||
<!-- Npgsql 10.0.1 requires Microsoft.EntityFrameworkCore >= 10.0.4; keep in sync -->
|
<!-- Npgsql 10.0.1 requires Microsoft.EntityFrameworkCore >= 10.0.4; keep in sync -->
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.1" />
|
<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" Version="10.3.30" />
|
||||||
<PackageReference Include="Cerebellum.BlazorBlocks.Data.Postgres" Version="10.3.30" />
|
<PackageReference Include="Cerebellum.BlazorBlocks.Data.Postgres" Version="10.3.30" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -5,9 +5,6 @@
|
|||||||
# Expects in ${APP_HOME}/staging/:
|
# Expects in ${APP_HOME}/staging/:
|
||||||
# deepdrft-manager.tar.gz -- published self-contained linux-x64 binary tree
|
# 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.
|
# Paths are derived at runtime — no hardcoded usernames or home dirs.
|
||||||
# APP_HOME comes from $HOME (sshd sets this for the app user).
|
# 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"
|
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 ─────────────────────────────────────────────
|
# ── Enable and restart service ─────────────────────────────────────────────
|
||||||
systemctl --user enable deepdrftmanager.service
|
systemctl --user enable deepdrftmanager.service
|
||||||
systemctl --user restart deepdrftmanager.service
|
systemctl --user restart deepdrftmanager.service
|
||||||
|
|||||||
@@ -5,9 +5,6 @@
|
|||||||
# Expects in ${APP_HOME}/staging/:
|
# Expects in ${APP_HOME}/staging/:
|
||||||
# deepdrft-public.tar.gz -- published self-contained linux-x64 binary tree
|
# 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.
|
# Paths are derived at runtime — no hardcoded usernames or home dirs.
|
||||||
# APP_HOME comes from $HOME (sshd sets this for the app user).
|
# 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"
|
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 ─────────────────────────────────────────────
|
# ── Enable and restart service ─────────────────────────────────────────────
|
||||||
systemctl --user enable deepdrftpublic.service
|
systemctl --user enable deepdrftpublic.service
|
||||||
systemctl --user restart deepdrftpublic.service
|
systemctl --user restart deepdrftpublic.service
|
||||||
|
|||||||
@@ -92,7 +92,6 @@ need_cred() {
|
|||||||
if need_cred "filedatabase"; then
|
if need_cred "filedatabase"; then
|
||||||
write_cred "filedatabase" \
|
write_cred "filedatabase" \
|
||||||
"{\"FileDatabaseSettings\":{\"VaultPath\":\"${APP_HOME}/api/deepdrft/vaults\"}}"
|
"{\"FileDatabaseSettings\":{\"VaultPath\":\"${APP_HOME}/api/deepdrft/vaults\"}}"
|
||||||
cp "${CREDDIR}/filedatabase.json" "${APP_HOME}/api/deepdrft/environment/filedatabase.json"
|
|
||||||
else
|
else
|
||||||
echo "[setup-step10-creds] filedatabase.json already exists, skipping"
|
echo "[setup-step10-creds] filedatabase.json already exists, skipping"
|
||||||
fi
|
fi
|
||||||
@@ -111,7 +110,6 @@ if need_cred "apikey"; then
|
|||||||
unset API_KEY_INPUT
|
unset API_KEY_INPUT
|
||||||
write_cred "apikey" \
|
write_cred "apikey" \
|
||||||
"{\"ApiKeySettings\":{\"ApiKey\":\"$(json_escape "${API_KEY}")\"}}"
|
"{\"ApiKeySettings\":{\"ApiKey\":\"$(json_escape "${API_KEY}")\"}}"
|
||||||
cp "${CREDDIR}/apikey.json" "${APP_HOME}/api/deepdrft/environment/apikey.json"
|
|
||||||
else
|
else
|
||||||
echo "[setup-step10-creds] apikey.json already exists, skipping"
|
echo "[setup-step10-creds] apikey.json already exists, skipping"
|
||||||
# Still need the value for api-manager.json if that's also being written.
|
# 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}")"
|
AUTH_CONN="Host=localhost;Database=${DB_AUTH};Username=${PG_ROLE};Password=$(json_escape "${PG_PASSWORD}")"
|
||||||
write_cred "connections" \
|
write_cred "connections" \
|
||||||
"{\"ConnectionStrings\":{\"DefaultConnection\":\"${META_CONN}\",\"Auth\":\"${AUTH_CONN}\"}}"
|
"{\"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
|
unset PG_PASSWORD META_CONN AUTH_CONN
|
||||||
else
|
else
|
||||||
echo "[setup-step10-creds] connections.json already exists, skipping"
|
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}")"}}
|
{"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
|
JSON
|
||||||
)"
|
)"
|
||||||
cp "${CREDDIR}/authblocks.json" "${APP_HOME}/api/deepdrft/environment/authblocks.json"
|
|
||||||
unset JWT_SECRET JWT_ISSUER JWT_AUDIENCE EMAIL_HOST EMAIL_TOKEN
|
unset JWT_SECRET JWT_ISSUER JWT_AUDIENCE EMAIL_HOST EMAIL_TOKEN
|
||||||
unset ADMIN_USERNAME ADMIN_EMAIL ADMIN_PASSWORD SUPPORT_EMAIL
|
unset ADMIN_USERNAME ADMIN_EMAIL ADMIN_PASSWORD SUPPORT_EMAIL
|
||||||
else
|
else
|
||||||
@@ -218,7 +214,6 @@ fi
|
|||||||
if need_cred "api-public"; then
|
if need_cred "api-public"; then
|
||||||
write_cred "api-public" \
|
write_cred "api-public" \
|
||||||
"{\"Api\":{\"ContentApiUrl\":\"http://localhost:${PORT_API:-5002}\"}}"
|
"{\"Api\":{\"ContentApiUrl\":\"http://localhost:${PORT_API:-5002}\"}}"
|
||||||
cp "${CREDDIR}/api-public.json" "${APP_HOME}/public/environment/api.json"
|
|
||||||
else
|
else
|
||||||
echo "[setup-step10-creds] api-public.json already exists, skipping"
|
echo "[setup-step10-creds] api-public.json already exists, skipping"
|
||||||
fi
|
fi
|
||||||
@@ -232,7 +227,6 @@ if need_cred "api-manager"; then
|
|||||||
fi
|
fi
|
||||||
write_cred "api-manager" \
|
write_cred "api-manager" \
|
||||||
"{\"Api\":{\"ContentApiUrl\":\"http://localhost:${PORT_API:-5002}\",\"ContentApiKey\":\"$(json_escape "${API_KEY}")\"}}"
|
"{\"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
|
unset API_KEY
|
||||||
else
|
else
|
||||||
echo "[setup-step10-creds] api-manager.json already exists, skipping"
|
echo "[setup-step10-creds] api-manager.json already exists, skipping"
|
||||||
|
|||||||
Reference in New Issue
Block a user