""" Stage and deploy Workflow1111 to a Hugging Face Space. python apps/05_workflow1111/deploy_space.py --stage # build staging dir only python apps/05_workflow1111/deploy_space.py --push # create + upload The Space must be **public**: the reference-node sample images are referenced by their public `.../resolve/main/samples/...` URL, which is the only default shape the canvas renders *and* a remote inference provider can fetch. A private Space would serve 401s for those URLs and the defaults would come up blank. OAuth is enabled in the README frontmatter, so each visitor signs in and their own token pays for their own inference — the Space ships no token of its own. """ import argparse import os import shutil import sys HERE = os.path.dirname(os.path.abspath(__file__)) ROOT = os.path.abspath(os.path.join(HERE, "..", "..")) STAGE = os.path.join(HERE, "_space") SPACE_ID = os.environ.get("WORKFLOW1111_SPACE", "ysharma/Workflow1111") SHIP = [ "test_api.py", "deploy_space.py", "app.py", "nodes.py", "workflow.json", "requirements.txt", "build_workflow.py", "layout.json", "make_samples.py", "test_nodes.py", "test_pipelines.py", ] FRONTMATTER = """--- title: Workflow1111 Diffusion Studio emoji: 🎨 colorFrom: indigo colorTo: purple sdk: gradio sdk_version: 6.22.0 app_file: app.py pinned: false license: mit hf_oauth: true hf_oauth_scopes: - inference-api short_description: Automatic1111-style studio on one gr.Workflow canvas --- > **Sign in with Hugging Face** (button at the top right) before running > anything. This Space carries no token of its own — every `model`, `space` and > inference-calling `fn` node runs on *your* token and your own inference quota. """ def read_token(): for path in (os.path.join(ROOT, "hf-write-token.txt"),): if os.path.exists(path): with open(path, encoding="utf-8") as f: tok = f.read().strip() if tok: return tok tok = os.environ.get("HF_TOKEN") if tok: return tok raise SystemExit("No write token found (hf-write-token.txt or HF_TOKEN).") def stage(): if os.path.exists(STAGE): shutil.rmtree(STAGE) os.makedirs(STAGE) for name in SHIP: src = os.path.join(HERE, name) if not os.path.exists(src): raise SystemExit(f"missing file to ship: {name}") shutil.copy2(src, os.path.join(STAGE, name)) samples_src = os.path.join(HERE, "samples") samples_dst = os.path.join(STAGE, "samples") os.makedirs(samples_dst) for name in sorted(os.listdir(samples_src)): if name.startswith("_"): continue shutil.copy2(os.path.join(samples_src, name), os.path.join(samples_dst, name)) with open(os.path.join(HERE, "README.md"), encoding="utf-8") as f: body = f.read() with open(os.path.join(STAGE, "README.md"), "w", encoding="utf-8") as f: f.write(FRONTMATTER + body) # Nothing secret may ever reach the Space. for dirpath, _dirs, files in os.walk(STAGE): for name in files: low = name.lower() if "token" in low and low.endswith(".txt"): raise SystemExit(f"refusing to ship {name}") total = sum(os.path.getsize(os.path.join(d, f)) for d, _s, fs in os.walk(STAGE) for f in fs) files = [os.path.relpath(os.path.join(d, f), STAGE) for d, _s, fs in os.walk(STAGE) for f in fs] print(f"staged {len(files)} files ({total // 1024} KB) in {os.path.relpath(STAGE, os.getcwd())}") for f in sorted(files): size = os.path.getsize(os.path.join(STAGE, f)) // 1024 print(f" {f:34} {size:>5} KB") return files def push(): from huggingface_hub import HfApi api = HfApi(token=read_token()) who = api.whoami() print(f"authenticated as: {who.get('name')}") url = api.create_repo(repo_id=SPACE_ID, repo_type="space", space_sdk="gradio", exist_ok=True, private=False) print(f"space repo ready: {url}") api.upload_folder( folder_path=STAGE, repo_id=SPACE_ID, repo_type="space", commit_message="Workflow1111 — Automatic1111-style diffusion studio on gr.Workflow", ) print(f"uploaded → https://huggingface.co/spaces/{SPACE_ID}") if __name__ == "__main__": ap = argparse.ArgumentParser() ap.add_argument("--stage", action="store_true") ap.add_argument("--push", action="store_true") args = ap.parse_args() if not (args.stage or args.push): ap.error("pass --stage or --push") stage() if args.push: push()