net10, pointed at PrivaPub, and deployed as a static site to decepub.thepra.dev
Build / Build (push) Successful in 18s
Deploy / decepub.thepra.dev (push) Successful in 1m11s

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:
thepraandClaude Opus 5.5 committed 2026-10-01 08:09:45 +02:00
1 parent 872d1460f8
commit b9dc865053
15 files changed
+226 -35

No files matched your search

+26
View File
@@ -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
+72
View File
@@ -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"
+2 -2
View File
@@ -1,4 +1,4 @@
using Blazored.LocalStorage;
using Blazored.LocalStorage;
using collAnon.Client.Services;
@@ -11,7 +11,7 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using SocialPub.ClientModels;
using PrivaPub.ClientModels;
using System.Collections.Specialized;
using System.ComponentModel;
+2 -1
View File
@@ -1,6 +1,7 @@
namespace decePubClient.Models;
namespace decePubClient.Models;
public class AppConfiguration
{
public string Version { get; set; }
public string ApiBaseAddress { get; set; }
}
+2 -2
View File
@@ -1,5 +1,5 @@
using SocialPub.ClientModels.Resources;
using PrivaPub.ClientModels.Resources;
using System.ComponentModel.DataAnnotations;
+3 -2
View File
@@ -12,7 +12,7 @@ using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using SocialPub.ClientModels;
using PrivaPub.ClientModels;
using collAnon.Client.Services;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
@@ -51,9 +51,10 @@ builder.Services.AddOptions()
.AddLogging(lb => lb.SetMinimumLevel(LogLevel.Debug))
.AddIndexedDb();
var apiBaseAddress = builder.Configuration["AppConfiguration:ApiBaseAddress"];
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"));
});
+2 -2
View File
@@ -1,8 +1,8 @@
using decePubClient.Resources;
using decePubClient.Resources;
using Microsoft.Extensions.Localization;
using SocialPub.ClientModels.Resources;
using PrivaPub.ClientModels.Resources;
namespace collAnon.Client.Services
{
+10 -13
View File
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<Nullable>disable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
@@ -10,18 +10,15 @@
<ItemGroup>
<PackageReference Include="BlazorZXingJs" Version="0.5.13" />
<PackageReference Include="BuildBundlerMinifier" Version="3.2.449" />
<PackageReference Include="BuildWebCompiler" Version="1.12.405" PrivateAssets="all" />
<PackageReference Include="BundlerMinifier.Core" Version="3.2.449" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="7.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.1" PrivateAssets="all" />
<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="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.9" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="10.0.9" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.9" PrivateAssets="all" />
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.9" />
<PackageReference Include="BlazorDownloadFileFast" Version="1.0.0.1" />
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
<PackageReference Include="DnetIndexedDb" Version="2.4.1" />
<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" />
</ItemGroup>
@@ -77,7 +74,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SocialPub\SocialPub\SocialPub.ClientModels\SocialPub.ClientModels.csproj" />
<ProjectReference Include="..\SocialPub\PrivaPub.ClientModels\PrivaPub.ClientModels.csproj" />
</ItemGroup>
<ItemGroup>
+37
View File
@@ -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"
+5
View File
@@ -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;
+56
View File
@@ -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;
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"sdk": {
"version": "10.0.100",
"rollForward": "latestFeature",
"allowPrerelease": false
}
}
+2 -12
View File
@@ -1,16 +1,6 @@
{
"Local": {
"Authority": "https://openidconnect.net",
"ClientId": "1234.locahost",
"RedirectUri": "",
"MetadataUrl": "",
"PostLogoutRedirectUri": "",
"ResponseType": "",
"ResponseMode": "",
"AdditionalProviderParameters": [],
"DefaultScopes": []
},
"AppConfiguration": {
"Version": "0.1"
"Version": "0.1",
"ApiBaseAddress": "https://privapub.thepra.dev"
}
}
Binary file not shown.
-1
View File
@@ -22,7 +22,6 @@
<script src="rxjs.7.4.0.min.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.HotKeys/script.min.js"></script>
<script>navigator.serviceWorker.register('service-worker.js');</script>
<script src="main.js"></script>