Spaces:
Paused
Paused
Download app.py from ChBysk/AndroidSDK-on-CPU: direct link, hf CLI and curl.
- Browser
- Download file 4.46 kB
-
https://huggingface.co/spaces/ChBysk/AndroidSDK-on-CPU/resolve/main/app.py
- Command line
-
hf download hf://spaces/ChBysk/AndroidSDK-on-CPU/app.py
-
curl -L -o app.py https://huggingface.co/spaces/ChBysk/AndroidSDK-on-CPU/resolve/main/app.py
4.46 kB
| """ | |
| Flask-based UI + proxy to the Android build-runner. | |
| Configuration: | |
| - BUILD_RUNNER_URL (env): base URL of your build-runner, e.g. https://runpod-host.example | |
| - DEFAULT_API_KEY (env): optional default API key to send to build-runner | |
| - PORT (env): port (default 8080) | |
| """ | |
| import os | |
| from flask import Flask, send_from_directory, request, jsonify, Response, redirect | |
| import requests | |
| BUILD_RUNNER = os.environ.get("BUILD_RUNNER_URL", "").rstrip("/") | |
| DEFAULT_API_KEY = os.environ.get("DEFAULT_API_KEY", "") | |
| if not BUILD_RUNNER: | |
| # App will still run locally; advise user to set BUILD_RUNNER_URL | |
| print("WARNING: BUILD_RUNNER_URL not set. UI will not be able to trigger builds until set.") | |
| app = Flask(__name__, static_folder="static", static_url_path="/static") | |
| def forward_headers(incoming): | |
| headers = {} | |
| # Accept an API key from the UI (header or form) or fallback to DEFAULT_API_KEY | |
| api_key = incoming.headers.get("X-API-KEY") or incoming.args.get("api_key") or incoming.form.get("api_key") or DEFAULT_API_KEY | |
| if api_key: | |
| headers["X-API-KEY"] = api_key | |
| return headers | |
| def index(): | |
| return send_from_directory("static", "index.html") | |
| # Proxy endpoints | |
| def build(): | |
| if not BUILD_RUNNER: | |
| return jsonify({"error": "BUILD_RUNNER_URL not configured"}), 500 | |
| headers = forward_headers(request) | |
| # If UI sends a file (multipart), forward as-stream | |
| if request.content_type and request.content_type.startswith("multipart/"): | |
| files = {} | |
| data = {} | |
| # forward known fields | |
| for k in request.form: | |
| data[k] = request.form[k] | |
| if 'file' in request.files: | |
| f = request.files['file'] | |
| files['file'] = (f.filename, f.stream, f.mimetype) | |
| resp = requests.post(f"{BUILD_RUNNER}/build", headers=headers, data=data, files=files, timeout=300) | |
| else: | |
| # JSON body (repo_url etc) | |
| payload = request.get_json(force=False) or request.form.to_dict() | |
| resp = requests.post(f"{BUILD_RUNNER}/build", headers=headers, json=payload, timeout=300) | |
| return Response(resp.content, status=resp.status_code, content_type=resp.headers.get("content-type", "application/json")) | |
| def status(job_id): | |
| if not BUILD_RUNNER: | |
| return jsonify({"error": "BUILD_RUNNER_URL not configured"}), 500 | |
| headers = forward_headers(request) | |
| resp = requests.get(f"{BUILD_RUNNER}/status/{job_id}", headers=headers, timeout=30) | |
| return Response(resp.content, status=resp.status_code, content_type=resp.headers.get("content-type", "application/json")) | |
| def logs(job_id): | |
| if not BUILD_RUNNER: | |
| return jsonify({"error": "BUILD_RUNNER_URL not configured"}), 500 | |
| headers = forward_headers(request) | |
| resp = requests.get(f"{BUILD_RUNNER}/logs/{job_id}", headers=headers, stream=True, timeout=300) | |
| def stream(): | |
| for chunk in resp.iter_content(chunk_size=4096): | |
| if chunk: | |
| yield chunk | |
| return Response(stream(), status=resp.status_code, content_type=resp.headers.get("content-type", "text/plain")) | |
| def artifact(job_id, name): | |
| if not BUILD_RUNNER: | |
| return jsonify({"error": "BUILD_RUNNER_URL not configured"}), 500 | |
| headers = forward_headers(request) | |
| # The build-runner returns artifact URLs in status; we can redirect by trying to fetch the status and locating artifact URL. | |
| resp = requests.get(f"{BUILD_RUNNER}/status/{job_id}", headers=headers, timeout=10) | |
| if resp.status_code != 200: | |
| return Response(resp.content, status=resp.status_code, content_type=resp.headers.get("content-type", "application/json")) | |
| data = resp.json() | |
| for a in data.get("artifacts", []): | |
| if a.get("name") == name: | |
| url = a.get("url") | |
| # If url is a relative path on the runner, convert to full URL | |
| if url.startswith("/"): | |
| return redirect(BUILD_RUNNER + url) | |
| else: | |
| return redirect(url) | |
| return jsonify({"error": "artifact not found"}), 404 | |
| # Serve static assets under /static/* automatically | |
| # (Flask static_folder handles it) | |
| if __name__ == "__main__": | |
| port = int(os.environ.get("PORT", 8080)) | |
| app.run(host="0.0.0.0", port=port) |