chore: import upstream snapshot with attribution
regression / regression-shards (style-16-prod style-9-prod style-17-prod iframe-render-compat variables-prod mp4-h265-sdr, shard-4) (push) Has been cancelled
regression / regression-shards (style-4-prod style-11-prod style-2-prod animejs-adapter typegpu-adapter parallel-capture-regression, shard-5) (push) Has been cancelled
regression / regression-shards (style-7-prod style-8-prod style-10-prod css-spinner-render-compat webm-transparency mp4-h264-sdr webm-vp9, shard-3) (push) Has been cancelled
regression / regression-shards (sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector, shard-7) (push) Has been cancelled
Windows render verification / Detect changes (push) Has been cancelled
Windows render verification / Preflight (lint + format) (push) Has been cancelled
Windows render verification / Render on windows-latest (push) Has been cancelled
Windows render verification / Tests on windows-latest (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Fallow audit (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Producer: integration tests (push) Has been cancelled
CI / Producer: unit tests (push) Has been cancelled
CI / File size check (push) Has been cancelled
CI / Test: skills (push) Has been cancelled
CI / Skills: manifest in sync (push) Has been cancelled
CI / CLI: npx shim (macos-latest) (push) Has been cancelled
CI / CLI: npx shim (ubuntu-latest) (push) Has been cancelled
CI / CLI: npx shim (windows-latest) (push) Has been cancelled
CI / SDK: unit + contract + smoke (push) Has been cancelled
CI / Test: runtime contract (push) Has been cancelled
CI / Studio: load smoke (push) Has been cancelled
CI / Smoke: global install (push) Has been cancelled
CI / CLI smoke (required) (push) Has been cancelled
CI / Semantic PR title (push) Has been cancelled
Player perf / Detect changes (push) Has been cancelled
Player perf / Preflight (lint + format) (push) Has been cancelled
Player perf / player-perf (push) Has been cancelled
Player perf / Perf: drift (push) Has been cancelled
Player perf / Perf: fps (push) Has been cancelled
Player perf / Perf: parity (push) Has been cancelled
Player perf / Perf: scrub (push) Has been cancelled
Player perf / Perf: load (push) Has been cancelled
preview-regression / Detect changes (push) Has been cancelled
preview-regression / Preflight (lint + format) (push) Has been cancelled
preview-regression / Preview parity (push) Has been cancelled
preview-regression / preview-regression (push) Has been cancelled
regression / regression (push) Has been cancelled
regression / Detect changes (push) Has been cancelled
regression / Preflight (lint + format) (push) Has been cancelled
regression / regression-shards (hdr-regression style-5-prod style-3-prod mov-prores, shard-1) (push) Has been cancelled
regression / regression-shards (overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence portrait-edge-bleed, shard-6) (push) Has been cancelled
regression / regression-shards (style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat audio-mux-parity, shard-8) (push) Has been cancelled
regression / regression-shards (style-15-prod hdr-hlg-regression style-1-prod many-cuts vfr-screen-recording render-symlinked-assets, shard-2) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Docs / Validate docs (push) Has been cancelled
Sync skills to ClawHub / Publish changed skills (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:58:35 +08:00
commit 85453da49f
4031 changed files with 710987 additions and 0 deletions
@@ -0,0 +1,7 @@
# Local Terraform working files — never commit these.
.terraform/
.terraform.lock.hcl
*.tfstate
*.tfstate.*
*.tfvars
crash.log
+197
View File
@@ -0,0 +1,197 @@
# HyperFrames distributed render stack on Google Cloud.
#
# Topology (the GCP twin of the AWS Lambda adapter's SAM template):
#
# GCS bucket ←→ Cloud Run service (plan / renderChunk / assemble)
# ▲
# │ OIDC-authenticated http.post per step
# │
# Cloud Workflows (Plan → parallel RenderChunk → Assemble)
#
# Two service accounts keep least-privilege boundaries:
# - run_sa : the render service's identity; read/write the bucket only.
# - workflow_sa: the workflow's identity; invoke the render service only.
locals {
workflow_source = var.workflow_source_path != "" ? var.workflow_source_path : "${path.module}/workflow.yaml"
name = var.project_name
}
# ── Storage: plan tarballs, chunk outputs, final renders ─────────────────────
resource "google_storage_bucket" "render" {
name = "${local.name}-render-${var.project_id}"
project = var.project_id
location = var.region
uniform_bucket_level_access = true
force_destroy = var.bucket_force_destroy
# Render artifacts (plan tarballs, chunk files) are disposable scratch.
# Sweep them after 7 days so the bucket doesn't accumulate cost; final
# outputs that adopters want to keep should be copied elsewhere.
lifecycle_rule {
condition {
age = 7
}
action {
type = "Delete"
}
}
}
# ── Service accounts ─────────────────────────────────────────────────────────
resource "google_service_account" "run_sa" {
account_id = "${local.name}-run"
project = var.project_id
display_name = "HyperFrames render service (Cloud Run)"
}
resource "google_service_account" "workflow_sa" {
account_id = "${local.name}-wf"
project = var.project_id
display_name = "HyperFrames render orchestration (Workflows)"
}
# Render service reads inputs + writes outputs in the render bucket only.
resource "google_storage_bucket_iam_member" "run_sa_bucket" {
bucket = google_storage_bucket.render.name
role = "roles/storage.objectAdmin"
member = "serviceAccount:${google_service_account.run_sa.email}"
}
# ── Cloud Run render service ─────────────────────────────────────────────────
resource "google_cloud_run_v2_service" "render" {
name = "${local.name}-render"
project = var.project_id
location = var.region
# Authenticated only — no public invoker binding. Only the workflow SA can
# call it. Ingress stays "all" because Workflows reaches the service over
# Google's front door, not the VPC.
ingress = "INGRESS_TRAFFIC_ALL"
# Let `terraform destroy` (and replacement on image bumps) remove the
# service without a manual console step. The render service is stateless —
# all durable artifacts live in GCS.
deletion_protection = false
template {
service_account = google_service_account.run_sa.email
timeout = "${var.request_timeout_seconds}s"
# One render (chunk / plan / assemble) per instance — each uses the whole
# box's CPU + memory + /tmp. The workflow's concurrency_limit governs how
# many instances run at once.
max_instance_request_concurrency = 1
scaling {
min_instance_count = var.min_instances
max_instance_count = var.max_instances
}
containers {
image = var.image
resources {
limits = {
cpu = var.cpu
memory = var.memory
}
# Keep CPU allocated only during request processing (request-based
# billing). Renders are entirely request-scoped.
cpu_idle = true
}
env {
# Scopes every event's GCS URIs to this bucket (the handler's
# GCS_URI_NOT_ALLOWED guard). Defense against request injection.
name = "HYPERFRAMES_RENDER_BUCKET"
value = google_storage_bucket.render.name
}
startup_probe {
http_get {
path = "/healthz"
}
timeout_seconds = 5
period_seconds = 10
failure_threshold = 6
}
}
}
}
# Only the workflow's identity may invoke the render service.
resource "google_cloud_run_v2_service_iam_member" "workflow_invokes_run" {
name = google_cloud_run_v2_service.render.name
project = var.project_id
location = var.region
role = "roles/run.invoker"
member = "serviceAccount:${google_service_account.workflow_sa.email}"
}
# ── Cloud Workflows orchestration ────────────────────────────────────────────
resource "google_workflows_workflow" "render" {
name = "${local.name}-render"
project = var.project_id
region = var.region
service_account = google_service_account.workflow_sa.id
source_contents = file(local.workflow_source)
# Allow `terraform destroy` to remove the workflow without a manual step;
# the definition is reproducible from this module.
deletion_protection = false
}
# ── Runaway-request alert (backstop against a fan-out bug) ────────────────────
resource "google_monitoring_alert_policy" "runaway_requests" {
project = var.project_id
display_name = "${local.name}-render runaway request count"
combiner = "OR"
conditions {
display_name = "Render service request count > threshold (1h)"
condition_threshold {
filter = join(" AND ", [
"resource.type = \"cloud_run_revision\"",
"resource.labels.service_name = \"${google_cloud_run_v2_service.render.name}\"",
"metric.type = \"run.googleapis.com/request_count\"",
])
comparison = "COMPARISON_GT"
threshold_value = var.render_request_alarm_threshold
duration = "0s"
aggregations {
alignment_period = "3600s"
per_series_aligner = "ALIGN_SUM"
}
}
}
notification_channels = var.notification_channels
}
# ── Workflow-failure alert ───────────────────────────────────────────────────
# Request-count alone misses a render that fails 100% of the time at low
# volume. Alert on any FAILED workflow execution so a broken render path is
# visible even when traffic is light.
resource "google_monitoring_alert_policy" "workflow_failures" {
project = var.project_id
display_name = "${local.name}-render workflow execution failures"
combiner = "OR"
conditions {
display_name = "Failed workflow executions (5m)"
condition_threshold {
filter = join(" AND ", [
"resource.type = \"workflows.googleapis.com/Workflow\"",
"resource.labels.workflow_id = \"${google_workflows_workflow.render.name}\"",
"metric.type = \"workflows.googleapis.com/finished_execution_count\"",
"metric.labels.status = \"FAILED\"",
])
comparison = "COMPARISON_GT"
threshold_value = 0
duration = "0s"
aggregations {
alignment_period = "300s"
per_series_aligner = "ALIGN_SUM"
}
}
}
notification_channels = var.notification_channels
}
@@ -0,0 +1,34 @@
output "render_bucket_name" {
description = "GCS bucket holding plan tarballs, chunk outputs, and final renders. Pass as renderToCloudRun({ bucketName })."
value = google_storage_bucket.render.name
}
output "service_url" {
description = "HTTPS URL of the Cloud Run render service. Pass as renderToCloudRun({ serviceUrl })."
value = google_cloud_run_v2_service.render.uri
}
output "workflow_name" {
description = "Workflow id. Pass as renderToCloudRun({ workflowId })."
value = google_workflows_workflow.render.name
}
output "workflow_id_full" {
description = "Fully-qualified workflow resource name."
value = google_workflows_workflow.render.id
}
output "run_service_account_email" {
description = "Render service identity (read/write the render bucket)."
value = google_service_account.run_sa.email
}
output "workflow_service_account_email" {
description = "Workflow identity (invokes the render service)."
value = google_service_account.workflow_sa.email
}
output "region" {
description = "Region everything was deployed into. Pass as renderToCloudRun({ location })."
value = var.region
}
@@ -0,0 +1,12 @@
# This module is applied directly (by `examples/gcp-cloud-run/scripts/smoke.sh`
# and `hyperframes cloudrun deploy`), so it configures the google provider
# from its own variables. Credentials come from the environment — either
# Application Default Credentials (`gcloud auth application-default login`)
# or a `GOOGLE_OAUTH_ACCESS_TOKEN` env var.
#
# If you instead embed this as a CHILD module, delete this block and pass a
# configured provider from your root module.
provider "google" {
project = var.project_id
region = var.region
}
@@ -0,0 +1,75 @@
variable "project_id" {
type = string
description = "GCP project id to deploy the render stack into."
}
variable "region" {
type = string
description = "Region for the Cloud Run service, Workflow, and bucket."
default = "us-central1"
}
variable "project_name" {
type = string
description = "Name prefix applied to the service / workflow / bucket / service accounts."
default = "hyperframes"
}
variable "image" {
type = string
description = "Fully-qualified container image for the render service (e.g. us-central1-docker.pkg.dev/PROJECT/REPO/hyperframes-render:TAG), built from packages/gcp-cloud-run/Dockerfile."
}
variable "cpu" {
type = string
description = "vCPU per Cloud Run instance. Allowed: 1, 2, 4, 8. Renders are CPU-bound; 4 is a good default."
default = "4"
}
variable "memory" {
type = string
description = "Memory per Cloud Run instance. Must be ≥ 2Gi per vCPU at cpu=4. Headroom for Chrome + ffmpeg + the chunk's frames in /tmp."
default = "16Gi"
}
variable "request_timeout_seconds" {
type = number
description = "Per-request timeout. Cloud Run hard cap is 3600s; a single chunk should finish well inside this."
default = 3600
}
variable "min_instances" {
type = number
description = "Min Cloud Run instances. Default 0 (scale-to-zero) is cheapest but means the first render after idle pays a cold start (image pull + Chrome + bun boot, ~20-30s). Set to 1 to keep one warm if first-render latency matters."
default = 0
}
variable "max_instances" {
type = number
description = "Max Cloud Run instances. Each chunk pins one instance (request concurrency = 1), and the workflow fans out up to the plan's chunk count (which never exceeds Config.maxParallelChunks). Keep this >= the largest maxParallelChunks you render with, or excess chunks queue behind 429s + retry backoff. Also a runaway-cost backstop."
default = 100
}
variable "workflow_source_path" {
type = string
description = "Path to the Cloud Workflows YAML. Defaults to the copy shipped with this module."
default = ""
}
variable "render_request_alarm_threshold" {
type = number
description = "Cloud Monitoring alert fires when render-service request count exceeds this in a 1-hour window. Backstop against a runaway fan-out."
default = 1000
}
variable "notification_channels" {
type = list(string)
description = "Cloud Monitoring notification channel ids for the runaway-request alert. Empty disables notifications (the policy still records)."
default = []
}
variable "bucket_force_destroy" {
type = bool
description = "Allow `terraform destroy` to delete the render bucket even when it still holds objects. Off by default to match the AWS adapter's RETAIN policy."
default = false
}
@@ -0,0 +1,9 @@
terraform {
required_version = ">= 1.5.0"
required_providers {
google = {
source = "hashicorp/google"
version = ">= 5.0.0"
}
}
}
@@ -0,0 +1,179 @@
# HyperFrames distributed render orchestration on Cloud Workflows.
#
# Plan → BuildChunkList → AssertChunkCount → RenderChunks (parallel) → Assemble
#
# Mirrors the Step Functions state machine in
# `examples/aws-lambda/template.yaml`. Every step POSTs to the same Cloud Run
# service URL (passed in as `args.ServiceUrl`) and varies only the body's
# `Action`. The service returns the step's small result body on 2xx; on a
# non-retryable failure it returns HTTP 400, on a retryable failure HTTP 5xx —
# the `retryable` predicate below keys off exactly that split.
#
# The final returned object accumulates every step's result body so
# `getRenderProgress` can read frame totals + per-step durations on success:
# { Plan: {...}, Chunks: [{...}, ...], Assemble: {...} }
#
# Deploy with `gcloud workflows deploy` (the Terraform module / the
# `hyperframes cloudrun deploy` command do this for you).
main:
params: [args]
steps:
- init:
assign:
- serviceUrl: ${args.ServiceUrl}
- projectGcsUri: ${args.ProjectGcsUri}
- planOutputGcsPrefix: ${args.PlanOutputGcsPrefix}
- outputGcsUri: ${args.OutputGcsUri}
- config: ${args.Config}
# ── Plan (Activity A) ────────────────────────────────────────────────────
- plan:
try:
call: http.post
args:
url: ${serviceUrl}
timeout: 1800
auth:
type: OIDC
body:
Action: plan
ProjectGcsUri: ${projectGcsUri}
PlanOutputGcsPrefix: ${planOutputGcsPrefix}
Config: ${config}
result: planResp
retry:
predicate: ${retryable}
max_retries: 4
backoff:
initial_delay: 2
max_delay: 60
multiplier: 2
- capturePlan:
assign:
- planResult: ${planResp.body}
- chunkCount: ${planResult.ChunkCount}
# ── BuildChunkList + AssertChunkCount ──────────────────────────────────────
- assertChunkCount:
switch:
- condition: ${chunkCount > 0}
next: buildChunkList
next: planProducedZeroChunks
- planProducedZeroChunks:
raise:
code: PLAN_PRODUCED_ZERO_CHUNKS
message: "Plan returned ChunkCount=0 — the composition produced no frames. Non-retryable producer-side invariant violation."
- buildChunkList:
# Pre-size the ordered chunk-URI + per-chunk result lists so the
# parallel branches below assign by index (distinct indices, no
# read-modify-write race on a shared accumulator).
assign:
- chunkIndexes: []
- chunkUris: []
- chunkResults: []
- fillLists:
for:
value: i
range: [0, ${chunkCount - 1}]
steps:
- appendSlots:
assign:
- chunkIndexes: ${list.concat(chunkIndexes, i)}
- chunkUris: ${list.concat(chunkUris, "")}
- chunkResults: ${list.concat(chunkResults, "")}
# ── RenderChunks (Activity B, fanned out) ──────────────────────────────────
- renderChunks:
parallel:
shared: [chunkUris, chunkResults]
# Run up to chunkCount chunks at once, clamped to 20 — Cloud
# Workflows hard-caps concurrent branches/iterations per execution
# at 20 (https://cloud.google.com/workflows/quotas). Above that,
# iterations queue regardless of concurrency_limit, so a config with
# maxParallelChunks > 20 still renders correctly; the extra chunks
# just wait. All chunkCount iterations always run.
concurrency_limit: ${math.min(chunkCount, 20)}
for:
value: idx
in: ${chunkIndexes}
steps:
- renderOneChunk:
try:
call: http.post
args:
url: ${serviceUrl}
timeout: 1800
auth:
type: OIDC
body:
Action: renderChunk
ChunkIndex: ${idx}
PlanGcsUri: ${planResult.PlanGcsUri}
PlanHash: ${planResult.PlanHash}
ChunkOutputGcsPrefix: ${planOutputGcsPrefix}
Format: ${planResult.Format}
result: chunkResp
retry:
predicate: ${retryable}
max_retries: 4
backoff:
initial_delay: 2
max_delay: 60
multiplier: 2
- storeChunk:
assign:
- chunkUris[idx]: ${chunkResp.body.ChunkGcsUri}
- chunkResults[idx]: ${chunkResp.body}
# ── Assemble (Activity C) ──────────────────────────────────────────────────
- assemble:
try:
call: http.post
args:
url: ${serviceUrl}
timeout: 1800
auth:
type: OIDC
body:
Action: assemble
PlanGcsUri: ${planResult.PlanGcsUri}
ChunkGcsUris: ${chunkUris}
AudioGcsUri: ${planResult.AudioGcsUri}
OutputGcsUri: ${outputGcsUri}
Format: ${planResult.Format}
# Forward the caller's exact-CFR request (Config.cfr) to assemble.
# `"cfr" in config` guards the optional key; when unset this is
# false, which the handler reads as the default -c copy path.
Cfr: ${("cfr" in config) and config.cfr}
result: assembleResp
retry:
predicate: ${retryable}
max_retries: 4
backoff:
initial_delay: 2
max_delay: 60
multiplier: 2
- done:
return:
Plan: ${planResult}
Chunks: ${chunkResults}
Assemble: ${assembleResp.body}
# Retry predicate: retry transient/server failures (429 + 5xx), never the
# handler's non-retryable 400s (bad input, plan-hash mismatch, unsupported
# format, …). Connection / timeout errors carry no `.code`; retry those too.
retryable:
params: [e]
steps:
- classify:
switch:
- condition: ${not("code" in e)}
return: true
- condition: ${e.code == 429}
return: true
- condition: ${e.code >= 500 and e.code < 600}
return: true
- nonRetryable:
return: false