[FA-5] Adds image support with proper S3 upload and replacement after upload

This commit is contained in:
gamer147
2025-11-23 21:16:26 -05:00
parent 573a0f6e3f
commit 16ed16ff62
33 changed files with 1321 additions and 267 deletions

View File

@@ -21,6 +21,11 @@
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="8.0.7" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2"/>
</ItemGroup>
<!-- Builds the Fusion graph file before building the application itself -->
<Target Name="RunFusionBuild" BeforeTargets="BeforeBuild">
<Exec Command="python build_gateway.py" WorkingDirectory="$(ProjectDir)" />
</Target>
<ItemGroup>
<Content Include="..\.dockerignore">

View File

@@ -1,138 +0,0 @@
<#
.SYNOPSIS
Export GraphQL schemas, pack subgraphs and compose the gateway (PowerShell).
.DESCRIPTION
- Searches for FictionArchive.Service.* folders one directory above this script.
- Reads skip-projects.txt next to the script.
- Builds each service (Release).
- Runs `dotnet run --no-build --no-launch-profile -- schema export` in each service to avoid running the web host.
- Packs subgraphs.
- Composes the gateway from FictionArchive.API.
#>
[CmdletBinding()]
param()
function Write-ErrExit {
param($Message, $Code = 1)
Write-Error $Message
exit $Code
}
# Resolve directories
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
$ServicesDir = Resolve-Path -Path (Join-Path $ScriptDir '..') -ErrorAction Stop
$ApiDir = Join-Path $ServicesDir 'FictionArchive.API'
Write-Host "Script dir: $ScriptDir"
Write-Host "Services dir: $ServicesDir"
# Load skip list
$SkipFile = Join-Path $ScriptDir 'gateway_skip.txt'
$SkipList = @()
Write-Host "----------------------------------------"
Write-Host " Loading skip list..."
Write-Host "----------------------------------------"
if (Test-Path $SkipFile) {
$SkipList = Get-Content $SkipFile |
ForEach-Object { $_.Trim() } |
Where-Object { $_ -and -not $_.StartsWith('#') }
Write-Host "Skipping: $($SkipList -join ', ')"
} else {
Write-Warning "skip-projects.txt not found — no services will be skipped."
}
# Find service directories
Write-Host
Write-Host "----------------------------------------"
Write-Host " Finding GraphQL services..."
Write-Host "----------------------------------------"
$servicePattern = 'FictionArchive.Service.*'
$serviceDirs = Get-ChildItem -Path $ServicesDir -Directory -Filter 'FictionArchive.Service.*'
if (-not $serviceDirs) {
Write-ErrExit "No service folders found matching FictionArchive.Service.* under $ServicesDir"
}
$selectedServices = @()
foreach ($d in $serviceDirs) {
if ($SkipList -contains $d.Name) {
Write-Host "Skipping: $($d.Name)"
continue
}
Write-Host "Found: $($d.Name)"
$selectedServices += $d.FullName
}
if (-not $selectedServices) {
Write-ErrExit "All services skipped — nothing to do."
}
# Export schemas and pack subgraphs
Write-Host
Write-Host "----------------------------------------"
Write-Host " Exporting schemas & packing subgraphs..."
Write-Host "----------------------------------------"
foreach ($svcPath in $selectedServices) {
$svcName = Split-Path -Leaf $svcPath
Write-Host "`nProcessing: $svcName"
Push-Location $svcPath
try {
# Build Release
Write-Host "Building $svcName..."
dotnet build -c Release
if ($LASTEXITCODE -ne 0) { Write-ErrExit "dotnet build failed for $svcName" }
# Schema export using dotnet run (no server)
Write-Host "Running schema export..."
dotnet run --no-build --no-launch-profile -- schema export --output schema.graphql
if ($LASTEXITCODE -ne 0) { Write-ErrExit "Schema export failed for $svcName" }
# Pack subgraph
Write-Host "Running fusion subgraph pack..."
fusion subgraph pack
if ($LASTEXITCODE -ne 0) { Write-ErrExit "fusion subgraph pack failed for $svcName" }
Write-Host "Completed: $svcName"
}
finally {
Pop-Location
}
}
# Compose gateway
Write-Host
Write-Host "----------------------------------------"
Write-Host " Running fusion compose..."
Write-Host "----------------------------------------"
if (-not (Test-Path $ApiDir)) {
Write-ErrExit "API directory not found: $ApiDir"
}
Push-Location $ApiDir
try {
if (Test-Path "gateway.fgp") { Remove-Item "gateway.fgp" -Force }
foreach ($svcPath in $selectedServices) {
$svcName = Split-Path -Leaf $svcPath
Write-Host "Composing: $svcName"
fusion compose -p gateway.fgp -s ("..\" + $svcName)
if ($LASTEXITCODE -ne 0) { Write-ErrExit "fusion compose failed for $svcName" }
}
Write-Host "`nFusion build complete!"
}
finally {
Pop-Location
}
exit 0

View File

@@ -0,0 +1,129 @@
#!/usr/bin/env python3
import subprocess
import sys
import os
from pathlib import Path
# ----------------------------------------
# Helpers
# ----------------------------------------
def run(cmd, cwd=None):
"""Run a command and exit on failure."""
print(f"> {' '.join(cmd)}")
result = subprocess.run(cmd, cwd=cwd)
if result.returncode != 0:
print(f"ERROR: command failed in {cwd or os.getcwd()}")
sys.exit(result.returncode)
def load_skip_list(skip_file: Path):
if not skip_file.exists():
print(f"WARNING: skip-projects.txt not found at {skip_file}")
return set()
lines = skip_file.read_text().splitlines()
skip = {line.strip() for line in lines
if line.strip() and not line.strip().startswith("#")}
print("Skip list:", ", ".join(skip) if skip else "(none)")
return skip
# ----------------------------------------
# Setup paths
# ----------------------------------------
script_dir = Path(__file__).parent.resolve()
services_dir = (script_dir / "..").resolve()
api_dir = services_dir / "FictionArchive.API"
print(f"Script dir: {script_dir}")
print(f"Services dir: {services_dir}")
skip_file = script_dir / "gateway_skip.txt"
skip_list = load_skip_list(skip_file)
# ----------------------------------------
# Find services
# ----------------------------------------
print("\n----------------------------------------")
print(" Finding GraphQL services...")
print("----------------------------------------")
service_dirs = [
d for d in services_dir.glob("FictionArchive.Service.*")
if d.is_dir()
]
selected_services = []
for d in service_dirs:
name = d.name
if name in skip_list:
print(f"Skipping: {name}")
else:
print(f"Found: {name}")
selected_services.append(d)
if not selected_services:
print("No services to process. Exiting.")
sys.exit(0)
# ----------------------------------------
# Export + pack
# ----------------------------------------
print("\n----------------------------------------")
print(" Exporting schemas & packing subgraphs...")
print("----------------------------------------")
for svc in selected_services:
name = svc.name
print(f"\nProcessing {name}")
# Build once
run(["dotnet", "build", "-c", "Release"], cwd=svc)
# Export schema
run([
"dotnet", "run",
"--no-build",
"--no-launch-profile",
"--",
"schema", "export",
"--output", "schema.graphql"
], cwd=svc)
# Pack subgraph
run(["fusion", "subgraph", "pack"], cwd=svc)
# ----------------------------------------
# Compose gateway
# ----------------------------------------
print("\n----------------------------------------")
print(" Running fusion compose...")
print("----------------------------------------")
if not api_dir.exists():
print(f"ERROR: FictionArchive.API not found at {api_dir}")
sys.exit(1)
gateway_file = api_dir / "gateway.fgp"
if gateway_file.exists():
gateway_file.unlink()
for svc in selected_services:
name = svc.name
print(f"Composing: {name}")
run([
"fusion", "compose",
"-p", "gateway.fgp",
"-s", f"..{os.sep}{name}"
], cwd=api_dir)
print("\n----------------------------------------")
print(" Fusion build complete!")
print("----------------------------------------")

View File

@@ -1,112 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
###############################################
# Resolve important directories
###############################################
# Directory where this script lives
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Services live one directory above the script's directory
SERVICES_DIR="$(cd "$ROOT/.." && pwd)"
###############################################
# Skip list (folder names, match exactly)
###############################################
SKIP_FILE="$ROOT/gateway_skip.txt"
SKIP_PROJECTS=()
if [[ -f "$SKIP_FILE" ]]; then
# Read non-empty lines ignoring comments
while IFS= read -r line; do
[[ -z "$line" || "$line" =~ ^# ]] && continue
SKIP_PROJECTS+=("$line")
done < "$SKIP_FILE"
else
echo "WARNING: skip-projects.txt not found — no projects will be skipped."
fi
echo "----------------------------------------"
echo " Finding GraphQL services..."
echo "----------------------------------------"
SERVICE_LIST=()
# Convert skip projects into a single searchable string
SKIP_STRING=" ${SKIP_PROJECTS[*]} "
# Find service directories
shopt -s nullglob
for FOLDER in "$SERVICES_DIR"/FictionArchive.Service.*; do
[ -d "$FOLDER" ] || continue
PROJECT_NAME="$(basename "$FOLDER")"
# Skip entries that match the skip list
if [[ "$SKIP_STRING" == *" $PROJECT_NAME "* ]]; then
echo "Skipping service: $PROJECT_NAME"
continue
fi
echo "Found service: $PROJECT_NAME"
SERVICE_LIST+=("$FOLDER")
done
shopt -u nullglob
echo
echo "----------------------------------------"
echo " Exporting schemas and packing subgraphs..."
echo "----------------------------------------"
for SERVICE in "${SERVICE_LIST[@]}"; do
PROJECT_NAME="$(basename "$SERVICE")"
echo "Processing service: $PROJECT_NAME"
pushd "$SERVICE" >/dev/null
echo "Building service..."
dotnet build -c Release >/dev/null
# Automatically detect built DLL in bin/Release/<TFM>/
DLL_PATH="$(find "bin/Release" -maxdepth 3 -name '*.dll' | head -n 1)"
if [[ -z "$DLL_PATH" ]]; then
echo "ERROR: Could not locate DLL for $PROJECT_NAME"
popd >/dev/null
exit 1
fi
echo "Running schema export..."
dotnet exec "$DLL_PATH" schema export --output schema.graphql
echo "Running subgraph pack..."
fusion subgraph pack
popd >/dev/null
echo "Completed: $PROJECT_NAME"
echo
done
echo "----------------------------------------"
echo " Running fusion compose..."
echo "----------------------------------------"
pushd "$ROOT" >/dev/null
# Remove old composition file
rm -f gateway.fgp
for SERVICE in "${SERVICE_LIST[@]}"; do
SERVICE_NAME="$(basename "$SERVICE")"
echo "Composing subgraph: $SERVICE_NAME"
# Note: Fusion compose must reference parent dir (services live above ROOT)
fusion compose -p gateway.fgp -s "../$SERVICE_NAME"
done
popd >/dev/null
echo "----------------------------------------"
echo " Fusion build complete!"
echo "----------------------------------------"