summaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--web/README.md43
-rw-r--r--web/index.php78
2 files changed, 93 insertions, 28 deletions
diff --git a/web/README.md b/web/README.md
index e79abd4..bd87e11 100644
--- a/web/README.md
+++ b/web/README.md
@@ -1,15 +1,15 @@
1# Download page 1# Download page
2 2
3`index.php` scans `bin/client` and `bin/server` on every request and renders 3`index.php` scans `bin/gui`, `bin/client` and `bin/server` on every request and
4whatever builds it finds, with version, size and SHA-256. No database, no 4renders whatever builds it finds, with version, size and SHA-256. No database, no JavaScript, no CSS, no dependencies. The page is plain
5JavaScript, no CSS, no dependencies. The page is plain browser defaults: 5browser defaults: black text, blue links, monospace checksums. PHP 8.0+.
6black text, blue links, monospace checksums. PHP 8.0+.
7 6
8## Layout 7## Layout
9 8
10``` 9```
11web/ 10web/
12 index.php 11 index.php
12 bin/gui/ served at /bin/gui/... (app and installers)
13 bin/client/ served at /bin/client/... 13 bin/client/ served at /bin/client/...
14 bin/server/ served at /bin/server/... 14 bin/server/ served at /bin/server/...
15``` 15```
@@ -22,13 +22,22 @@ The page only lists files that match the release pattern; anything else in
22those directories is ignored. 22those directories is ignored.
23 23
24``` 24```
25zagan-bet-client-<version>-<platform>-<arch>[.exe] 25bin/gui/zagan-bet-gui-<version>-<platform>-<arch>[.exe]
26zagan-bet-server-<version>-<platform>-<arch> 26bin/gui/zagan-bet-gui-<version>-<platform>-<arch>-install.sh
27bin/gui/zagan-bet-gui-<version>-<platform>-<arch>-install.ps1
28bin/client/zagan-bet-client-<version>-<platform>-<arch>[.exe]
29bin/server/zagan-bet-server-<version>-<platform>-<arch>[.exe]
27``` 30```
28 31
29`<version>` is `MAJOR.MINOR.PATCH`, `<platform>` is `linux`, `windows` or 32`<version>` is `MAJOR.MINOR.PATCH`, `<platform>` is `linux`, `windows` or
30`macos`, `<arch>` is `x86_64`, `i686` or `aarch64`. 33`macos`, `<arch>` is `x86_64`, `i686` or `aarch64`.
31 34
35The installers are generated next to their app. They embed the app's SHA-256,
36check the file (or download it) and install it for the current user: Linux
37writes `~/.local/bin/zagan-bet-gui` plus a `.desktop` launcher, Windows writes
38`%LOCALAPPDATA%\Programs\Zagan-Bet` plus a Start-menu shortcut. The source
39archives satisfy the GPL's corresponding-source requirement.
40
32## Publishing a build 41## Publishing a build
33 42
34From the repository root: 43From the repository root:
@@ -37,15 +46,21 @@ From the repository root:
37./scripts/publish.sh 46./scripts/publish.sh
38``` 47```
39 48
40It reads the version from `Cargo.toml`, builds all four artifacts and installs 49It reads the version from `Cargo.toml`, builds every artifact and installs
41them under `web/bin` with the names above. Override the destination with 50them under `web/bin` with the names above. The GUI is built with the
42`DEST=/srv/www/bin ./scripts/publish.sh`. 51workspace's `gui-release` profile (LTO, stripped) and the installers are
52rendered with Python 3 and the published SHA-256. Run it from a clean tree so
53the release commit is the source the page links to. Override the destination
54with `DEST=/srv/www/bin ./scripts/publish.sh`, and the download origin baked
55into the installers with `URL_BASE=https://staging.example/ ./scripts/publish.sh`.
56`ALLOW_DIRTY=1` skips the clean-tree check for a preview.
43 57
44Builds are per target triple, so these must be installed: 58Builds are per target triple, so these must be installed:
45`x86_64-unknown-linux-gnu`, `i686-unknown-linux-gnu` and 59`x86_64-unknown-linux-gnu`, `i686-unknown-linux-gnu` and
46`x86_64-pc-windows-gnu`, plus the mingw linker for the Windows build. Client 60`x86_64-pc-windows-gnu`, plus the mingw linker for the Windows build. Client
47builds always pass `--no-default-features`, which drops the server's OpenSSL 61builds always pass `--no-default-features`, which drops the server's OpenSSL
48dependency; the client is rustls-only. 62dependency; the client is rustls-only. The GUI needs Python 3 at publish time
63for the installer templates in `scripts/installers/`.
49 64
50Cargo itself cannot produce these names: it always writes 65Cargo itself cannot produce these names: it always writes
51`target/<triple>/release/<bin>`. The script renames after each build. 66`target/<triple>/release/<bin>`. The script renames after each build.
@@ -100,8 +115,9 @@ Then open <http://127.0.0.1:8899/>.
100``` 115```
101 116
102`deploy.sh` rsyncs `web/` with `--delay-updates`, so a visitor never sees a 117`deploy.sh` rsyncs `web/` with `--delay-updates`, so a visitor never sees a
103half-written binary, then fetches the live page and every artifact it lists and 118half-written binary, then fetches the live page and every artifact it lists —
104compares the downloaded bytes with the local SHA-256. `--verify-only` skips the 119GUI apps, installers, terminal clients and servers — and compares the
120downloaded bytes with the local SHA-256. `--verify-only` skips the
105upload and only checks the live site. Old versions are left on the server; 121upload and only checks the live site. Old versions are left on the server;
106prune them by hand. 122prune them by hand.
107 123
@@ -124,3 +140,6 @@ php -S 127.0.0.1:8899 -t /srv/staging
124 stay downloadable until you remove them from `bin/`. 140 stay downloadable until you remove them from `bin/`.
125- The checksum block is in `sha256sum` format, so visitors can save it as 141- The checksum block is in `sha256sum` format, so visitors can save it as
126 `SHA256SUMS` and run `sha256sum -c SHA256SUMS`. 142 `SHA256SUMS` and run `sha256sum -c SHA256SUMS`.
143- The page links <https://git.2137697.xyz/zagan-bet.git> for the GPL
144 corresponding source; publish only from a committed release so that link
145 contains the exact source.
diff --git a/web/index.php b/web/index.php
index 7ed79da..77edf95 100644
--- a/web/index.php
+++ b/web/index.php
@@ -4,20 +4,23 @@ declare(strict_types=1);
4/** 4/**
5 * zagan.bet download page. 5 * zagan.bet download page.
6 * 6 *
7 * Scans ./bin/client and ./bin/server and renders every build it finds, with 7 * Scans ./bin/{gui,client,server} and renders every build it finds, with its
8 * its version, size and SHA-256. No database, no JavaScript, no dependencies. 8 * version, size and SHA-256. The GPL source link points at the public git
9 * repository. No database, no JavaScript, no dependencies.
9 * 10 *
10 * Expected file names (anything else is ignored): 11 * Expected file names (anything else is ignored):
11 * 12 *
12 * bin/client/zagan-bet-client-<version>-<platform>-<arch> 13 * bin/gui/zagan-bet-gui-<version>-<platform>-<arch>[.exe]
13 * bin/client/zagan-bet-client-<version>-<platform>-<arch>.exe 14 * bin/gui/zagan-bet-gui-<version>-<platform>-<arch>-install.sh
14 * bin/server/zagan-bet-server-<version>-<platform>-<arch> 15 * bin/gui/zagan-bet-gui-<version>-<platform>-<arch>-install.ps1
16 * bin/client/zagan-bet-client-<version>-<platform>-<arch>[.exe]
17 * bin/server/zagan-bet-server-<version>-<platform>-<arch>[.exe]
15 * 18 *
16 * <version> is MAJOR.MINOR.PATCH, <platform> is linux|windows|macos and 19 * <version> is MAJOR.MINOR.PATCH, <platform> is linux|windows|macos and
17 * <arch> is x86_64|i686|aarch64. Example: 20 * <arch> is x86_64|i686|aarch64. Example:
18 * 21 *
19 * bin/client/zagan-bet-client-3.1.1-linux-x86_64 22 * bin/gui/zagan-bet-gui-4.3.0-linux-x86_64
20 * bin/server/zagan-bet-server-3.1.1-linux-x86_64 23 * bin/client/zagan-bet-client-4.3.0-linux-x86_64
21 * 24 *
22 * SHA-256 values are cached in a JSON file keyed on size and mtime, so a file 25 * SHA-256 values are cached in a JSON file keyed on size and mtime, so a file
23 * is only re-read when it changes. The cache lives in the system temp 26 * is only re-read when it changes. The cache lives in the system temp
@@ -26,6 +29,10 @@ declare(strict_types=1);
26 */ 29 */
27 30
28const KINDS = [ 31const KINDS = [
32 'gui' => [
33 'title' => 'Desktop app',
34 'hint' => 'Windows 10 or newer, or a Linux desktop. No terminal needed.',
35 ],
29 'client' => [ 36 'client' => [
30 'title' => 'Client', 37 'title' => 'Client',
31 'hint' => 'Needs a terminal of at least 80×24 cells.', 38 'hint' => 'Needs a terminal of at least 80×24 cells.',
@@ -163,7 +170,7 @@ function read_release(
163 bool &$dirty 170 bool &$dirty
164): ?array { 171): ?array {
165 $pattern = '/^zagan-bet-' . preg_quote($kind, '/') 172 $pattern = '/^zagan-bet-' . preg_quote($kind, '/')
166 . '-v?(\d+\.\d+\.\d+)-([a-z]+)-([a-z0-9_]+)(\.exe)?$/i'; 173 . '-v?(\d+\.\d+\.\d+)-([a-z]+)-([a-z0-9_]+)(-install\.sh|-install\.ps1|\.exe)?$/i';
167 if (preg_match($pattern, $entry, $matches) !== 1) { 174 if (preg_match($pattern, $entry, $matches) !== 1) {
168 return null; 175 return null;
169 } 176 }
@@ -192,10 +199,14 @@ function read_release(
192 return null; 199 return null;
193 } 200 }
194 201
202 $suffix = strtolower($matches[4] ?? '');
203 $variant = str_starts_with($suffix, '-install.') ? 'installer' : 'binary';
204
195 return [ 205 return [
196 'version' => $matches[1], 206 'version' => $matches[1],
197 'platform' => strtolower($matches[2]), 207 'platform' => strtolower($matches[2]),
198 'arch' => strtolower($matches[3]), 208 'arch' => strtolower($matches[3]),
209 'variant' => $variant,
199 'file' => $entry, 210 'file' => $entry,
200 'size' => $size, 211 'size' => $size,
201 'mtime' => $mtime, 212 'mtime' => $mtime,
@@ -257,6 +268,10 @@ foreach (KINDS as $kind => $meta) {
257 if ($byArch !== 0) { 268 if ($byArch !== 0) {
258 return $byArch; 269 return $byArch;
259 } 270 }
271 $byVariant = ($a['variant'] === 'installer' ? 1 : 0) <=> ($b['variant'] === 'installer' ? 1 : 0);
272 if ($byVariant !== 0) {
273 return $byVariant;
274 }
260 return strcmp($a['file'], $b['file']); 275 return strcmp($a['file'], $b['file']);
261 }); 276 });
262 277
@@ -280,18 +295,41 @@ if ($cacheDirty) {
280<meta charset="utf-8"> 295<meta charset="utf-8">
281<meta name="viewport" content="width=device-width, initial-scale=1"> 296<meta name="viewport" content="width=device-width, initial-scale=1">
282<title>żagań.bet</title> 297<title>żagań.bet</title>
283<meta name="description" content="Official zagan.bet client and server downloads."> 298<meta name="description" content="Official zagan.bet desktop app, terminal client and server downloads.">
284<meta http-equiv="Content-Security-Policy" content="default-src 'none'"> 299<meta http-equiv="Content-Security-Policy" content="default-src 'none'">
285</head> 300</head>
286<body> 301<body>
287 302
288<h1>żagań.bet</h1> 303<h1>żagań.bet</h1>
289<p>Official client and server builds.</p> 304<p>Official desktop app, terminal client and server builds.</p>
290<?php if ($newest > 0): ?> 305<?php if ($newest > 0): ?>
291<p>Builds published <?= e(gmdate('j M Y H:i', $newest)) ?> UTC.</p> 306<p>Builds published <?= e(gmdate('j M Y H:i', $newest)) ?> UTC.</p>
292<?php endif; ?> 307<?php endif; ?>
293 308
294<h2>Client</h2> 309<h2>Desktop app</h2>
310<p>Windows 10 or newer, or a Linux desktop. No terminal needed.</p>
311<?php $guiBinaries = array_values(array_filter($releases['gui'], static fn (array $r): bool => $r['variant'] === 'binary')); ?>
312<?php $guiInstallers = array_values(array_filter($releases['gui'], static fn (array $r): bool => $r['variant'] === 'installer')); ?>
313<?php if ($guiBinaries === []): ?>
314<p>Nothing published yet.</p>
315<?php else: ?>
316<ul>
317<?php foreach ($guiBinaries as $release): ?>
318<li><a href="<?= e($release['href']) ?>" download><?= e(PLATFORMS[$release['platform']] ?? ucfirst($release['platform'])) ?> <?= e($release['arch']) ?><?php if (isset(ARCHES[$release['arch']])): ?> (<?= e(ARCHES[$release['arch']]) ?>)<?php endif; ?> v<?= e($release['version']) ?> — <?= e(human_size($release['size'])) ?></a></li>
319<?php endforeach; ?>
320</ul>
321<?php endif; ?>
322<?php if ($guiInstallers !== []): ?>
323<h3>Installers</h3>
324<p>The installer checks the download, installs Zagan-Bet for your user and adds it to your programs. Run it next to a downloaded app, or on its own to fetch one.</p>
325<ul>
326<?php foreach ($guiInstallers as $release): ?>
327<li><a href="<?= e($release['href']) ?>" download><?= e(PLATFORMS[$release['platform']] ?? ucfirst($release['platform'])) ?> <?= e($release['arch']) ?> installer (<?= str_ends_with($release['file'], '.ps1') ? 'PowerShell' : 'bash' ?>) v<?= e($release['version']) ?> — <?= e(human_size($release['size'])) ?></a></li>
328<?php endforeach; ?>
329</ul>
330<?php endif; ?>
331
332<h2>Terminal client</h2>
295<p>Needs a terminal of at least 80×24 cells.</p> 333<p>Needs a terminal of at least 80×24 cells.</p>
296<?php if ($releases['client'] === []): ?> 334<?php if ($releases['client'] === []): ?>
297<p>Nothing published yet.</p> 335<p>Nothing published yet.</p>
@@ -315,7 +353,7 @@ if ($cacheDirty) {
315</ul> 353</ul>
316<?php endif; ?> 354<?php endif; ?>
317 355
318<?php $all = array_merge($releases['client'], $releases['server']); ?> 356<?php $all = array_merge($releases['gui'], $releases['client'], $releases['server']); ?>
319<?php if ($all !== []): ?> 357<?php if ($all !== []): ?>
320<h2>SHA-256</h2> 358<h2>SHA-256</h2>
321<p>On Linux use <code>sha256sum &lt;file&gt;</code>. On Windows use <code>Get-FileHash &lt;file&gt;</code>.</p> 359<p>On Linux use <code>sha256sum &lt;file&gt;</code>. On Windows use <code>Get-FileHash &lt;file&gt;</code>.</p>
@@ -329,8 +367,17 @@ echo e($sums);
329?></pre> 367?></pre>
330<?php endif; ?> 368<?php endif; ?>
331 369
370<h2>Source</h2>
371<p>Zagan-Bet is free software under the GNU GPL v3 or later. The source for these builds is at <a href="https://git.2137697.xyz/zagan-bet.git">https://git.2137697.xyz/zagan-bet.git</a>.</p>
372
332<h2>Running it</h2> 373<h2>Running it</h2>
333<p>Client:</p> 374<p>Desktop app on Linux:</p>
375<pre><code>chmod +x zagan-bet-gui-*-linux-x86_64-install.sh
376./zagan-bet-gui-*-linux-x86_64-install.sh</code></pre>
377<p>Desktop app on Windows (PowerShell):</p>
378<pre><code>powershell -ExecutionPolicy Bypass -File .\zagan-bet-gui-*-windows-x86_64-install.ps1</code></pre>
379<p>The installers verify the SHA-256 before installing. You can also run the downloaded app directly.</p>
380<p>Terminal client:</p>
334<pre><code>chmod +x &lt;downloaded-client&gt; 381<pre><code>chmod +x &lt;downloaded-client&gt;
335./&lt;downloaded-client&gt;</code></pre> 382./&lt;downloaded-client&gt;</code></pre>
336<p>Server, first run creates <code>identity.p12</code>, <code>key.pem</code> and <code>cert.pem</code>:</p> 383<p>Server, first run creates <code>identity.p12</code>, <code>key.pem</code> and <code>cert.pem</code>:</p>
@@ -338,8 +385,7 @@ echo e($sums);
338./&lt;downloaded-server&gt; --init 385./&lt;downloaded-server&gt; --init
339./&lt;downloaded-server&gt; -i 0.0.0.0 -p 11525</code></pre> 386./&lt;downloaded-server&gt; -i 0.0.0.0 -p 11525</code></pre>
340 387
341<p>Windows: run the <code>.exe</code> from Windows Terminal or another real terminal.</p> 388<p>Terminal client on Windows: run the <code>.exe</code> from Windows Terminal or another real terminal.</p>
342 389<p>Run <code>help</code> inside the terminal client; the server binary supports <code>--help</code>.</p>
343<p>When lost, execute <code>help</code> command inside zagan.bet client. Server binary supports <code>--help</code> flag</p>
344</body> 390</body>
345</html> 391</html>