net10, pointed at PrivaPub, and deployed as a static site to decepub.thepra.dev
The project referenced ../SocialPub/SocialPub/SocialPub.ClientModels, a path that has not existed since the server became PrivaPub; it references ../SocialPub/PrivaPub.ClientModels now, and CI clones SocialPub beside it. Retargeted to net10.0 with the Microsoft packages at 10.0.9. BlazorDownloadFileFast moves to 1.0.0.1 because 0.2.0 used IJSUnmarshalledRuntime, which .NET 9 removed. The Visual Studio bundler and web compiler packages are gone; the bundle they produced, css/style.min.css, is committed and stays the stylesheet, and its stale .gz is deleted because .NET's static-asset compression writes that path itself. AppConfiguration.ApiBaseAddress (https://privapub.thepra.dev) is the API client's base address; the template's placeholder OIDC section and the Toolbelt.Blazor.HotKeys script tag, whose package is not referenced, are removed. The vhost sends noindex while the feed shows the prototype's mock posts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012CzABvBkbcFqoHdmi8b9WB
This commit is contained in:
1 parent
872d1460f8
commit
b9dc865053
15 files changed
+226
-35
No files matched your search
@@ -0,0 +1,26 @@
|
|||||||
|
name: Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build
|
||||||
|
runs-on: build
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
path: decePubClient
|
||||||
|
|
||||||
|
- name: Fetch PrivaPub's client models beside it
|
||||||
|
env:
|
||||||
|
READ_TOKEN: ${{ secrets.THEPRA_READ_TOKEN }}
|
||||||
|
run: |
|
||||||
|
rm -rf SocialPub
|
||||||
|
git -c http.extraHeader="Authorization: token $READ_TOKEN" clone -q --depth 1 \
|
||||||
|
https://git.thepra.dev/thepra/SocialPub.git SocialPub
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: dotnet build decePubClient/decePubClient.csproj -c Release
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
name: Deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
|
||||||
|
env:
|
||||||
|
WEB_ROOT: /var/www/decepub.thepra.dev
|
||||||
|
BACKUPS: /var/backups/decepub.thepra.dev
|
||||||
|
PUBLIC_URL: https://decepub.thepra.dev
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
site:
|
||||||
|
name: decepub.thepra.dev
|
||||||
|
runs-on: build
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
path: decePubClient
|
||||||
|
|
||||||
|
- name: Fetch PrivaPub's client models beside it
|
||||||
|
env:
|
||||||
|
READ_TOKEN: ${{ secrets.THEPRA_READ_TOKEN }}
|
||||||
|
run: |
|
||||||
|
rm -rf SocialPub
|
||||||
|
git -c http.extraHeader="Authorization: token $READ_TOKEN" clone -q --depth 1 \
|
||||||
|
https://git.thepra.dev/thepra/SocialPub.git SocialPub
|
||||||
|
|
||||||
|
- name: Resolve the build identity
|
||||||
|
run: |
|
||||||
|
echo "BUILD_COMMIT=$(echo "$GITHUB_SHA" | cut -c1-8)" >> "$GITHUB_ENV"
|
||||||
|
echo "BUILD_REF=${GITHUB_REF_NAME:-master}" >> "$GITHUB_ENV"
|
||||||
|
echo "BUILD_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
|
- name: Publish
|
||||||
|
run: |
|
||||||
|
rm -rf "$GITHUB_WORKSPACE/publish"
|
||||||
|
dotnet publish decePubClient/decePubClient.csproj -c Release -o "$GITHUB_WORKSPACE/publish"
|
||||||
|
printf '{"commit":"%s","buildRef":"%s","builtAt":"%s"}\n' "$BUILD_COMMIT" "$BUILD_REF" "$BUILD_TIME" \
|
||||||
|
> "$GITHUB_WORKSPACE/publish/wwwroot/build.json"
|
||||||
|
|
||||||
|
- name: Assert the publish actually produced a site
|
||||||
|
run: |
|
||||||
|
W="$GITHUB_WORKSPACE/publish/wwwroot"
|
||||||
|
for f in index.html appsettings.json build.json _framework/blazor.webassembly.js css/style.min.css; do
|
||||||
|
[ -e "$W/$f" ] || { echo "::error::publish output is missing $f"; exit 1; }
|
||||||
|
done
|
||||||
|
ls "$W/_framework" | grep -q '\.wasm$' || { echo "::error::no .wasm in _framework"; exit 1; }
|
||||||
|
echo "publish OK, $(du -sh "$W" | cut -f1)"
|
||||||
|
|
||||||
|
- name: Snapshot the live directory
|
||||||
|
run: |
|
||||||
|
STAMP=$(date +%Y%m%d-%H%M%S)
|
||||||
|
rsync -a "$WEB_ROOT/" "$BACKUPS/site-$STAMP/"
|
||||||
|
echo "SNAPSHOT=$BACKUPS/site-$STAMP" >> "$GITHUB_ENV"
|
||||||
|
ls -1dt "$BACKUPS"/site-* 2>/dev/null | tail -n +4 | xargs -r rm -rf || true
|
||||||
|
|
||||||
|
- name: Sync
|
||||||
|
run: rsync -a --delete "$GITHUB_WORKSPACE/publish/wwwroot/" "$WEB_ROOT/"
|
||||||
|
|
||||||
|
- name: Verify what is being served, roll back on failure
|
||||||
|
run: |
|
||||||
|
served=$(curl -fsS "$PUBLIC_URL/build.json" | python3 -c "import json,sys; print(json.load(sys.stdin).get('commit',''))" || true)
|
||||||
|
code=$(curl -s -o /dev/null -w '%{http_code}' "$PUBLIC_URL/some/client/route")
|
||||||
|
if [ "$served" != "$BUILD_COMMIT" ] || [ "$code" != "200" ]; then
|
||||||
|
echo "::error::served build '$served' (expected '$BUILD_COMMIT'), fallback route answered $code - rolling back"
|
||||||
|
rsync -a --delete "$SNAPSHOT/" "$WEB_ROOT/"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "::notice::serving $served"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using Blazored.LocalStorage;
|
using Blazored.LocalStorage;
|
||||||
|
|
||||||
using collAnon.Client.Services;
|
using collAnon.Client.Services;
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ using Microsoft.AspNetCore.Authorization;
|
|||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||||
|
|
||||||
using SocialPub.ClientModels;
|
using PrivaPub.ClientModels;
|
||||||
|
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
namespace decePubClient.Models;
|
namespace decePubClient.Models;
|
||||||
|
|
||||||
public class AppConfiguration
|
public class AppConfiguration
|
||||||
{
|
{
|
||||||
public string Version { get; set; }
|
public string Version { get; set; }
|
||||||
|
public string ApiBaseAddress { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
using SocialPub.ClientModels.Resources;
|
using PrivaPub.ClientModels.Resources;
|
||||||
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -12,7 +12,7 @@ using Microsoft.AspNetCore.Components.Web;
|
|||||||
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
|
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using SocialPub.ClientModels;
|
using PrivaPub.ClientModels;
|
||||||
using collAnon.Client.Services;
|
using collAnon.Client.Services;
|
||||||
|
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
||||||
@@ -51,9 +51,10 @@ builder.Services.AddOptions()
|
|||||||
.AddLogging(lb => lb.SetMinimumLevel(LogLevel.Debug))
|
.AddLogging(lb => lb.SetMinimumLevel(LogLevel.Debug))
|
||||||
.AddIndexedDb();
|
.AddIndexedDb();
|
||||||
|
|
||||||
|
var apiBaseAddress = builder.Configuration["AppConfiguration:ApiBaseAddress"];
|
||||||
builder.Services.AddHttpClient("default", client =>
|
builder.Services.AddHttpClient("default", client =>
|
||||||
{
|
{
|
||||||
client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress);
|
client.BaseAddress = new Uri(string.IsNullOrEmpty(apiBaseAddress) ? builder.HostEnvironment.BaseAddress : apiBaseAddress.TrimEnd('/') + "/");
|
||||||
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
using decePubClient.Resources;
|
using decePubClient.Resources;
|
||||||
|
|
||||||
using Microsoft.Extensions.Localization;
|
using Microsoft.Extensions.Localization;
|
||||||
|
|
||||||
using SocialPub.ClientModels.Resources;
|
using PrivaPub.ClientModels.Resources;
|
||||||
|
|
||||||
namespace collAnon.Client.Services
|
namespace collAnon.Client.Services
|
||||||
{
|
{
|
||||||
|
|||||||
+10
-13
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
|
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
<Nullable>disable</Nullable>
|
<Nullable>disable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
|
<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
|
||||||
@@ -10,18 +10,15 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BlazorZXingJs" Version="0.5.13" />
|
<PackageReference Include="BlazorZXingJs" Version="0.5.13" />
|
||||||
<PackageReference Include="BuildBundlerMinifier" Version="3.2.449" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.9" />
|
||||||
<PackageReference Include="BuildWebCompiler" Version="1.12.405" PrivateAssets="all" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="10.0.9" />
|
||||||
<PackageReference Include="BundlerMinifier.Core" Version="3.2.449" PrivateAssets="all" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.9" PrivateAssets="all" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.9" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="7.0.1" />
|
<PackageReference Include="BlazorDownloadFileFast" Version="1.0.0.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.1" PrivateAssets="all" />
|
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
|
|
||||||
<PackageReference Include="BlazorDownloadFileFast" Version="0.2.0" />
|
|
||||||
<PackageReference Include="Blazored.LocalStorage" Version="4.3.0" />
|
|
||||||
<PackageReference Include="DnetIndexedDb" Version="2.4.1" />
|
<PackageReference Include="DnetIndexedDb" Version="2.4.1" />
|
||||||
<PackageReference Include="Markdig" Version="0.30.4" />
|
<PackageReference Include="Markdig" Version="0.30.4" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="7.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Localization" Version="10.0.9" />
|
||||||
<PackageReference Include="Toolbelt.Blazor.HeadElement" Version="7.3.1" />
|
<PackageReference Include="Toolbelt.Blazor.HeadElement" Version="7.3.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@@ -77,7 +74,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\SocialPub\SocialPub\SocialPub.ClientModels\SocialPub.ClientModels.csproj" />
|
<ProjectReference Include="..\SocialPub\PrivaPub.ClientModels\PrivaPub.ClientModels.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Executable
+37
@@ -0,0 +1,37 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# One-time root setup on Max for decePubClient at decepub.thepra.dev (static files, no unit). Idempotent.
|
||||||
|
# rsync -a -e $MAX/ssh.sh deploy/ root@nuvola.xyz:/root/decepub-deploy/
|
||||||
|
# $MAX/run.sh bash /root/decepub-deploy/max/setup.sh
|
||||||
|
set -euo pipefail
|
||||||
|
SRC="${1:-/root/decepub-deploy}"
|
||||||
|
HOST=decepub.thepra.dev
|
||||||
|
RUNNER=build-runner
|
||||||
|
ACME=/root/.acme.sh/acme.sh
|
||||||
|
|
||||||
|
echo "== directories"
|
||||||
|
install -d -o "$RUNNER" -g www-data -m 755 /var/www/$HOST
|
||||||
|
install -d -o "$RUNNER" -g "$RUNNER" -m 750 /var/backups/$HOST
|
||||||
|
|
||||||
|
echo "== nginx snippet and bootstrap vhost"
|
||||||
|
install -m 644 "$SRC/nginx/decepub-headers.conf" /etc/nginx/snippets/decepub-headers.conf
|
||||||
|
if [ -f /root/.acme.sh/${HOST}_ecc/fullchain.cer ]; then
|
||||||
|
install -m 644 "$SRC/nginx/$HOST.conf" /etc/nginx/sites-available/$HOST.conf
|
||||||
|
else
|
||||||
|
awk '/^server \{/{n++} n==1' "$SRC/nginx/$HOST.conf" > /etc/nginx/sites-available/$HOST.conf
|
||||||
|
fi
|
||||||
|
ln -sf /etc/nginx/sites-available/$HOST.conf /etc/nginx/sites-enabled/$HOST.conf
|
||||||
|
nginx -t
|
||||||
|
systemctl reload nginx
|
||||||
|
|
||||||
|
echo "== certificate"
|
||||||
|
if [ -f /root/.acme.sh/${HOST}_ecc/fullchain.cer ]; then
|
||||||
|
echo "$HOST: certificate present"
|
||||||
|
else
|
||||||
|
$ACME --issue --server letsencrypt -d $HOST -w /var/www/acme --renew-hook "systemctl reload nginx"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "== full vhost"
|
||||||
|
install -m 644 "$SRC/nginx/$HOST.conf" /etc/nginx/sites-available/$HOST.conf
|
||||||
|
nginx -t
|
||||||
|
systemctl reload nginx
|
||||||
|
echo "setup complete"
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-Robots-Tag "noindex, nofollow" always;
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
server_name decepub.thepra.dev;
|
||||||
|
|
||||||
|
location ^~ /.well-known/acme-challenge/ {
|
||||||
|
root /var/www/acme;
|
||||||
|
default_type "text/plain";
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
listen 8444 ssl proxy_protocol;
|
||||||
|
listen [::]:443 ssl;
|
||||||
|
server_name decepub.thepra.dev;
|
||||||
|
http2 on;
|
||||||
|
|
||||||
|
include /etc/nginx/ssl.conf;
|
||||||
|
ssl_certificate /root/.acme.sh/decepub.thepra.dev_ecc/fullchain.cer;
|
||||||
|
ssl_certificate_key /root/.acme.sh/decepub.thepra.dev_ecc/decepub.thepra.dev.key;
|
||||||
|
include /etc/nginx/snippets/decepub-headers.conf;
|
||||||
|
|
||||||
|
access_log /var/log/nginx/decepub.thepra.dev.access.log;
|
||||||
|
error_log /var/log/nginx/decepub.thepra.dev.error.log;
|
||||||
|
|
||||||
|
root /var/www/decepub.thepra.dev;
|
||||||
|
index index.html;
|
||||||
|
gzip_static on;
|
||||||
|
open_file_cache off;
|
||||||
|
|
||||||
|
location ^~ /.well-known/acme-challenge/ {
|
||||||
|
root /var/www/acme;
|
||||||
|
default_type "text/plain";
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /index.html { expires -1; }
|
||||||
|
location = /build.json { expires -1; }
|
||||||
|
location = /appsettings.json { expires -1; }
|
||||||
|
location = /service-worker.js { expires -1; }
|
||||||
|
location = /service-worker-assets.js { expires -1; }
|
||||||
|
|
||||||
|
location ^~ /_framework/ {
|
||||||
|
expires 1h;
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
expires -1;
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"sdk": {
|
||||||
|
"version": "10.0.100",
|
||||||
|
"rollForward": "latestFeature",
|
||||||
|
"allowPrerelease": false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,6 @@
|
|||||||
{
|
{
|
||||||
"Local": {
|
|
||||||
"Authority": "https://openidconnect.net",
|
|
||||||
"ClientId": "1234.locahost",
|
|
||||||
"RedirectUri": "",
|
|
||||||
"MetadataUrl": "",
|
|
||||||
"PostLogoutRedirectUri": "",
|
|
||||||
"ResponseType": "",
|
|
||||||
"ResponseMode": "",
|
|
||||||
"AdditionalProviderParameters": [],
|
|
||||||
"DefaultScopes": []
|
|
||||||
},
|
|
||||||
"AppConfiguration": {
|
"AppConfiguration": {
|
||||||
"Version": "0.1"
|
"Version": "0.1",
|
||||||
|
"ApiBaseAddress": "https://privapub.thepra.dev"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Binary file not shown.
@@ -22,7 +22,6 @@
|
|||||||
<script src="rxjs.7.4.0.min.js"></script>
|
<script src="rxjs.7.4.0.min.js"></script>
|
||||||
<script src="_content/DnetIndexedDb/dnet-indexeddb.js"></script>
|
<script src="_content/DnetIndexedDb/dnet-indexeddb.js"></script>
|
||||||
<script src="_content/Toolbelt.Blazor.HeadElement.Services/script.min.js"></script>
|
<script src="_content/Toolbelt.Blazor.HeadElement.Services/script.min.js"></script>
|
||||||
<script src="_content/Toolbelt.Blazor.HotKeys/script.min.js"></script>
|
|
||||||
|
|
||||||
<script>navigator.serviceWorker.register('service-worker.js');</script>
|
<script>navigator.serviceWorker.register('service-worker.js');</script>
|
||||||
<script src="main.js"></script>
|
<script src="main.js"></script>
|
||||||
|
|||||||
Reference in new issue
Block a user