1
0
mirror of git://f0xx.org/android_cast synced 2026-07-29 04:18:09 +03:00

Add gzip-aware crash upload and OTA staging build/deploy tooling.

This restores the interrupted stash work on a dedicated feature branch, including backend decoding support, Dockerized build scripts, and staging channel artifacts for end-to-end OTA validation.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Anton Afanasyeu
2026-06-02 16:08:46 +02:00
parent 9f9d617730
commit 097c0790b8
18 changed files with 258 additions and 11 deletions

View File

@@ -109,6 +109,22 @@ curl -X POST http://127.0.0.1:8080/api/upload.php \
-d @../sample_crash_java.json
```
**Gzip ingest** (Android sends `Content-Encoding: gzip`; plain JSON still works):
```bash
./scripts/test_gzip_upload.sh
# BASE=https://apps.f0xx.org/app/androidcast_project/crashes ./scripts/test_gzip_upload.sh
```
On the **BE nginx** upload `location`, enable gunzip so PHP receives plain JSON (see `nginx.vm.conf`):
```nginx
gunzip on;
gunzip_types application/json;
```
PHP also decodes gzip if the header reaches FPM (`read_crash_upload_body()` in `bootstrap.php`). After deploy, sync `public/` + `src/` and reload nginx.
## Production (nginx + PHP-FPM)
**Deploy topology (FE/BE, ports, sshfs):** [docs/INFRA.md](../../../docs/INFRA.md).

View File

@@ -17,11 +17,13 @@ server {
}
location ~ ^/app/androidcast_project/crashes/api/upload\.php$ {
gunzip on;
gunzip_types application/json;
alias /var/www/androidcast_crashes/public/api/upload.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/androidcast_crashes/public/api/upload.php;
fastcgi_pass unix:/run/php-fpm/www.sock;
client_max_body_size 4m;
client_max_body_size 8m;
}
location ~ ^/app/androidcast_project/crashes/.+\.php$ {

View File

@@ -36,12 +36,15 @@ server {
}
location = /app/androidcast_project/crashes/api/upload.php {
# Decompress gzip uploads from Android before PHP (needs ngx_http_gunzip_module).
gunzip on;
gunzip_types application/json;
include fastcgi_params;
fastcgi_pass unix:/run/php-fpm.socket;
fastcgi_param SCRIPT_FILENAME /var/www/localhost/htdocs/apps/app/androidcast_project/android_cast/examples/crash_reporter/backend/public/api/upload.php;
fastcgi_param SCRIPT_NAME /app/androidcast_project/crashes/api/upload.php;
fastcgi_param REQUEST_URI $request_uri;
client_max_body_size 4m;
client_max_body_size 8m;
}
location ^~ /app/androidcast_project/crashes/ {

View File

@@ -13,10 +13,13 @@
declare(strict_types=1);
require_once __DIR__ . '/../../src/bootstrap.php';
$raw = file_get_contents('php://input');
if ($raw === false || $raw === '') {
$raw = read_crash_upload_body();
if ($raw === null) {
json_out(['ok' => false, 'error' => 'empty body'], 400);
}
if ($raw === false) {
json_out(['ok' => false, 'error' => 'invalid gzip body'], 400);
}
$data = json_decode($raw, true);
if (!is_array($data)) {
json_out(['ok' => false, 'error' => 'invalid json'], 400);

View File

@@ -0,0 +1,33 @@
#!/bin/sh
# Smoke-test gzip crash upload (plain JSON still accepted).
# Usage: BASE=http://127.0.0.1:8080/app/androidcast_project/crashes ./scripts/test_gzip_upload.sh
set -eu
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
SAMPLE="${ROOT}/../sample_crash_java.json"
BASE="${BASE:-http://127.0.0.1:8080/app/androidcast_project/crashes}"
URL="${BASE}/api/upload.php"
RID="gzip-test-$(date +%s)"
if [ ! -f "$SAMPLE" ]; then
echo "Missing $SAMPLE" >&2
exit 1
fi
BODY="$(mktemp)"
jq --arg rid "$RID" '.report_id = $rid' "$SAMPLE" > "$BODY"
GZIP="$(mktemp)"
gzip -c -f "$BODY" > "$GZIP"
echo "POST plain JSON..."
curl -sS -o /dev/null -w "plain:%{http_code}\n" -X POST "$URL" \
-H 'Content-Type: application/json' \
--data-binary @"$BODY"
echo "POST gzip (Content-Encoding: gzip)..."
curl -sS -w "\n%{http_code}\n" -X POST "$URL" \
-H 'Content-Type: application/json' \
-H 'Content-Encoding: gzip' \
--data-binary @"$GZIP"
rm -f "$BODY" "$GZIP"

View File

@@ -79,6 +79,25 @@ function json_out(array $data, int $code = 200): void {
exit;
}
/**
* Raw POST body for crash ingest. Supports plain JSON or Content-Encoding: gzip
* (when nginx gunzip is off or the client talks to PHP directly).
*
* @return string|null decoded JSON text, null if empty, false if gzip decode failed
*/
function read_crash_upload_body(): string|false|null {
$raw = file_get_contents('php://input');
if ($raw === false || $raw === '') {
return null;
}
$encoding = $_SERVER['HTTP_CONTENT_ENCODING'] ?? '';
if ($encoding !== '' && stripos($encoding, 'gzip') !== false) {
$decoded = @gzdecode($raw);
return $decoded === false ? false : $decoded;
}
return $raw;
}
/** Short lines for expandable list preview (not full report detail). */
function report_brief_lines(array $row, bool $grouped): array {
if ($grouped) {

View File

@@ -0,0 +1,4 @@
{
"schema": "v0",
"manifestUrl": "https://apps.f0xx.org/v0/ota/00/00.01/00.01.00/android_cast_00.01.00.00_manifest.json"
}