From 0d99c552eb3c9057a38fff9f4979e47cae97166b Mon Sep 17 00:00:00 2001 From: thepra Date: Thu, 15 Oct 2026 01:24:11 +0200 Subject: [PATCH] Workload install without build flags; CI variables and the APK key documented dotnet workload install refuses -nologo. CLAUDE.md lists every variable and secret the scripts and workflows read; the README gives the APK certificate's SHA-256. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012CzABvBkbcFqoHdmi8b9WB --- CLAUDE.md | 27 +++++++++++++++++++++++++++ README.md | 6 ++++++ tools/release.cs | 2 +- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index 0589c2d..21eeb91 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -24,6 +24,33 @@ dotnet publish src/MeWeb.Desktop -c Release -r osx-arm64 --self-contained The Android workload installs into the user SDK (`dotnet workload install android`); the system SDK in `/opt/dotnet` is root-owned, so CI uses the runner user's own `~/.dotnet` (passolo's `tools/release.sh` pattern). +## Repository, CI and the variables they read + +| Name | Where | What | +|---|---|---| +| `GITEA_URL` | shell, optional | Gitea base URL for `tools/gitea/*.sh`; default `https://git.thepra.dev` | +| `GITEA_ORG` | shell, optional | organisation; default `Arasaka` | +| `GITEA_REPO` | shell, optional | repository for `set_secret.sh`; default `MeWeb` | +| (git credential store) | `~/.git-credentials` | the only Gitea authentication the scripts use: `git credential fill` for `git.thepra.dev` | +| `MEWEB_KEYSTORE_B64` | Actions secret | the Android keystore, base64 (`tools/gitea/set_secret.sh`) | +| `MEWEB_KEYSTORE_PASS` | Actions secret | its password (store and key share it), alias `meweb` | +| `GITEA_TOKEN` | Actions, automatic | the job token; `release.sh` uses it as `RELEASE_TOKEN` to create the release and attach files | +| `VERSION`, `COMMIT` | job env | written by `.gitea/scripts/prepare.sh` from `Directory.Build.props` and the commit | +| `MEWEB_KEYSTORE` | release step | a temporary file in `$RUNNER_TEMP` decoded by `.gitea/scripts/android.sh`, removed on exit | + +`build.yml` runs on every push to `master`; `release.yml` on a `v*` tag (publishes the Gitea release) or by hand +(`publish: false` builds every platform and deploys the server only). Both run on the Arasaka org runner `nuvola`, +user `gitea-runner`, home `/var/lib/gitea-runner`: `tools/sdk.sh` installs the SDK from `global.json` into its +`~/.dotnet` (the system SDK in `/opt/dotnet` is older and root-owned), and the JDK, nfpm and the Android SDK are +cached in `~/.cache/meweb`. There is deliberately no `pull_request` trigger: the runner is the production box. + +The server's one-time root setup is `deploy/max/setup.sh` (user `meweb`, `/var/www/meweb.arasaka.software`, +`/etc/meweb/meweb.env`, the unit, the runner's sudoers line, the certificate, nginx), run on the box through +`arasaka.software`'s `tools/max/run.sh`. + +The Android release key: alias `meweb`, certificate SHA-256 +`5f52cff4f52f4e0b6da6cd044bfceaf78d1d42db24f2470602db7f19cbfdf846`. Never regenerate it. + ## Map | Path | What | diff --git a/README.md b/README.md index 178668e..1140142 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,12 @@ me-web? sends nothing anywhere unless a check needs it, and lists every host it the end you can choose to share your findings to improve the next release's map of providers; you see exactly what is sent first, and you can delete it afterwards. +## Verifying the Android app + +The APK is signed with the key whose certificate SHA-256 is +`5f:52:cf:f4:f5:2f:4e:0b:6d:a6:cd:04:4b:fc:ea:f7:8d:1d:42:db:24:f2:47:06:02:db:7f:19:cb:fd:f8:46` +(`apksigner verify --print-certs MeWeb--android.apk`). Every release also carries `SHA256SUMS.txt`. + ## Building See `CLAUDE.md`. .NET 10, Avalonia 12. diff --git a/tools/release.cs b/tools/release.cs index 58d730e..84e5808 100644 --- a/tools/release.cs +++ b/tools/release.cs @@ -301,7 +301,7 @@ string AndroidSdk(string jdk) void EnsureWorkload(string name) { var installed = Capture("dotnet", "workload", "list"); - if (!installed.Split('\n').Any(l => l.Trim().StartsWith(name + " ", StringComparison.Ordinal))) Dotnet(["workload", "install", name]); + if (!installed.Split('\n').Any(l => l.Trim().StartsWith(name + " ", StringComparison.Ordinal))) Run("dotnet", "workload", "install", name); } void WriteSums()