feat(app-studio): build → promote-to-production loop, build-doctor, private-image pull#420
Merged
Merged
Conversation
…r + private-image pull Close the app-studio dev→build→launch loop and everything the live testing surfaced. Core flow: a bound template scaffolds a per-component GitHub Actions build into the repo; Railpack builds+pushes one image per component to ghcr; the Code provider crawls the packages into Package CRs (tags+digests); app-studio reads those to gate promotion; promote stands up a separate <project>-prod instance of the same template running the built digests; the infra provider bridges a ghcr image-pull secret onto the runtime namespace's default SA so private images pull. app-studio: - imageInput link on template dev components; per-component build.json + matrix workflow (build+push only, no evidence-commit-back); build status + promote read ghcr Package CRs (no git evidence). - promote_project + POST /promote + GET /promotion; Publish & Promote portal tab (build status, Promote/Redeploy, prod URL). Fix: promote now provisions the artifact (production) environment (reconcileProjectLiveBindings only did live). - build-doctor: check_project_build + get_build_logs + rebuild_project; CI self-heals on template-bind and on commit (one idempotent ensure, no force UI). - ensureProjectRegistryPullSecret: mint a ghcr dockerconfigjson tenant Secret from the Code connection token at promote. code provider: - Package pipeline carries per-version tags/digests + imageRepository. - WorkflowRunReader/Dispatcher backend caps + RepositoryBuildStatus CR/controller + build_status/rebuild MCP tools (GitHub Actions status/logs/re-run). - oauth: request `workflow` scope (required to commit .github/workflows/*). infra provider: - application secret-bridge controller also bridges <instance>-registry into the runtime namespace + attaches it to the default ServiceAccount (all templates). Also folds in unrelated in-flight working-tree changes (agents provider, Tiltfiles, docs, databricks) at the author's request. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR completes an end-to-end App Studio “commit → CI build → package crawl → publish/promote to production” loop by wiring per-component build metadata (tags/digests/image repo) through the Code provider and exposing promotion/readiness endpoints and UI in App Studio. It also introduces a new standalone agents provider scaffold (API schemas + Helm chart + portal embedding) and updates infrastructure templates/CRDs to declare which dev components feed production image inputs.
Changes:
- Infrastructure templates/CRDs: add
development.components[].imageInputto link dev components to production schema image inputs. - Code provider: extend
Packagestatus withimageRepository+ version digests/tags; add workflow run inspection + rebuild tool plumbing. - App Studio: add promotion/readiness API + portal types/API calls; auto-ensure build workflow wiring on template bind and after commits.
Reviewed changes
Copilot reviewed 118 out of 124 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| Tiltfile.cluster | Adds Tilt resources to build/run/register/init/unregister the new agents provider in cluster dev loop. |
| Tiltfile | Adds Tilt resources to build/run/register/init/unregister the new agents provider in local dev loop. |
| providers/infrastructure/install/templates/simple-webapp.yaml | Declares imageInput for the simple-webapp dev component. |
| providers/infrastructure/install/templates/application.yaml | Declares imageInput for frontend/backend dev components. |
| providers/infrastructure/install/crds/infrastructure.kedge.faros.sh_templates.yaml | CRD schema update: adds imageInput field under development components (install bundle). |
| providers/infrastructure/config/crds/infrastructure.kedge.faros.sh_templates.yaml | CRD schema update: adds imageInput field under development components (config bundle). |
| providers/infrastructure/apis/v1alpha1/types_template.go | Adds ImageInput to TemplateDevelopmentComponent API type with validations. |
| providers/databricks/portal/package-lock.json | Updates Rollup platform package metadata in lockfile. |
| providers/databricks/portal/dist/.gitkeep | Removes the dist placeholder file. |
| providers/code/oauthgithub/oauth.go | Adds default workflow scope to GitHub OAuth scopes to enable writing workflow files. |
| providers/code/mcpserver/tools.go | Registers build-status-related MCP tools. |
| providers/code/deploy/chart/files/schemas/packages.code.kedge.faros.sh.yaml | Updates Packages APIResourceSchema to include image repo + versions in status (chart schema). |
| providers/code/controller/packages/controller.go | Persists imageRepository + version digests/tags into Package status and compares them for churn avoidance. |
| providers/code/controller_manager.go | Wires repository build status controller into the manager. |
| providers/code/config/kcp/apiresourceschema-packages.code.kedge.faros.sh.yaml | Updates Packages APIResourceSchema to include image repo + versions in status (kcp config). |
| providers/code/config/kcp/apiexport-code.kedge.faros.sh.yaml | Bumps packages schema ref and adds repositorybuildstatuses to the APIExport. |
| providers/code/config/crds/code.kedge.faros.sh_packages.yaml | Updates Package CRD schema to include imageRepository + versions. |
| providers/code/backend/interface.go | Extends backend interfaces for package versions/digests and workflow run inspection/dispatch. |
| providers/code/backend/github/backend.go | Adds GH packages version resolution and computes an image repository path for image packages. |
| providers/code/backend/github/actions.go | Implements workflow run status + job log tailing + dispatch for GitHub Actions. |
| providers/code/apis/v1alpha1/types_package.go | Adds ImageRepository + Versions to Package status and defines PackageVersion. |
| providers/code/apis/v1alpha1/groupversion_info.go | Registers RepositoryBuildStatus types with the scheme. |
| providers/app-studio/portal/src/workbench.ts | Renames the Publishing tab to “Publish & Promote”. |
| providers/app-studio/portal/src/workbench.test.mjs | Updates the corresponding workbench tab title test expectation. |
| providers/app-studio/portal/src/types.ts | Adds promotion/build status response types for the portal. |
| providers/app-studio/portal/src/api.ts | Adds getPromotion and promoteProject client calls. |
| providers/app-studio/api/tenant_resources.go | Adds a Code provider Package resource descriptor. |
| providers/app-studio/api/server.go | Registers new promotion/push-to-prod endpoints. |
| providers/app-studio/api/project_template.go | Parses imageInput, derives deterministic dev/prod instance names, and triggers build config wiring on template bind. |
| providers/app-studio/api/project_build_status_test.go | Adds unit tests for package/component build status resolution logic. |
| providers/app-studio/api/llm.go | Ensures build workflow wiring after successful commit tool calls and updates assistant guidance to use promote/build-doctor tools. |
| providers/app-studio/api/code_repository.go | Adds Code provider packages GVR. |
| providers/app-studio/api/assistant_tool.go | Assigns new build/promotion tools to workflow/runtime tool bundles. |
| providers/app-studio/api/assistant_tool_registry.go | Adds check_build/get_build_logs/rebuild/promote tools and wires build config on template selection. |
| providers/agents/store/memory_test.go | Adds in-memory store tests for messages, runs, usage, and inbox resolution. |
| providers/agents/provider.yaml | Adds admin Provider object manifest for provisioning agents provider workspace artifacts. |
| providers/agents/portal/vite.config.ts | Adds Vite build config for agents provider micro-frontend (IIFE main.js + assets/ chunks). |
| providers/agents/portal/tsconfig.json | Adds TypeScript config for agents portal. |
| providers/agents/portal/src/main.ts | Registers the <kedge-provider-agents> custom element and injects embedded CSS. |
| providers/agents/portal/README.md | Documents agents portal build and portal handshake. |
| providers/agents/portal/public/index.html | Adds a standalone fallback page when visiting the provider directly. |
| providers/agents/portal/public/icon.svg | Adds provider icon asset. |
| providers/agents/portal/package.json | Adds portal package manifest (Vite + TypeScript). |
| providers/agents/portal/.gitignore | Ignores node_modules/dist/logs for the agents portal. |
| providers/agents/manifest.yaml | Adds CatalogEntry manifest for agents provider routing + permission claims. |
| providers/agents/main.go | Adds agents provider main (serve/init subcommands) and HTTP server wiring. |
| providers/agents/init_cmd.go | Adds provider workspace bootstrap init command using provider-sdk install bootstrap. |
| providers/agents/heartbeat.go | Adds provider heartbeat loop to keep hub catalog Ready state current. |
| providers/agents/go.mod | Adds standalone Go module for provider-agents. |
| providers/agents/engine/engine.go | Adds Eino-based streaming single-turn chat engine implementation. |
| providers/agents/engine/engine_test.go | Adds engine streaming/usage extraction tests with a mock model. |
| providers/agents/Dockerfile | Adds multi-stage build (portal + Go binary) and distroless runtime image. |
| providers/agents/deploy/chart/values.yaml | Adds Helm values for agents provider (image, hub, store, catalog entry). |
| providers/agents/deploy/chart/templates/serviceaccount.yaml | Adds ServiceAccount template for agents provider. |
| providers/agents/deploy/chart/templates/service.yaml | Adds Service template for agents provider. |
| providers/agents/deploy/chart/templates/deployment.yaml | Adds Deployment template incl. init container bootstrap + provider runtime env wiring. |
| providers/agents/deploy/chart/templates/catalogentry.yaml | Adds CatalogEntry template rendered optionally as a ConfigMap for init-container apply. |
| providers/agents/deploy/chart/templates/_helpers.tpl | Adds standard Helm helper templates for naming/labels. |
| providers/agents/deploy/chart/files/schemas/connections.agents.kedge.faros.sh.yaml | Adds Connections APIResourceSchema for agents provider (chart schemas). |
| providers/agents/deploy/chart/files/schemas/agenttriggers.agents.kedge.faros.sh.yaml | Adds AgentTriggers APIResourceSchema for agents provider (chart schemas). |
| providers/agents/deploy/chart/files/schemas/agentschedules.agents.kedge.faros.sh.yaml | Adds AgentSchedules APIResourceSchema for agents provider (chart schemas). |
| providers/agents/deploy/chart/files/schemas/agentruns.agents.kedge.faros.sh.yaml | Adds AgentRuns APIResourceSchema for agents provider (chart schemas). |
| providers/agents/deploy/chart/Chart.yaml | Adds Helm chart metadata for agents provider. |
| providers/agents/config/kcp/apiresourceschema-connections.agents.kedge.faros.sh.yaml | Adds Connections APIResourceSchema (kcp config). |
| providers/agents/config/kcp/apiresourceschema-agenttriggers.agents.kedge.faros.sh.yaml | Adds AgentTriggers APIResourceSchema (kcp config). |
| providers/agents/config/kcp/apiresourceschema-agentschedules.agents.kedge.faros.sh.yaml | Adds AgentSchedules APIResourceSchema (kcp config). |
| providers/agents/config/kcp/apiresourceschema-agentruns.agents.kedge.faros.sh.yaml | Adds AgentRuns APIResourceSchema (kcp config). |
| providers/agents/config/kcp/apiexport-agents.kedge.faros.sh.yaml | Adds APIExport for agents provider. |
| providers/agents/config/crds/agents.kedge.faros.sh_agenttriggers.yaml | Adds Kubernetes CRD for AgentTriggers. |
| providers/agents/config/crds/agents.kedge.faros.sh_agentschedules.yaml | Adds Kubernetes CRD for AgentSchedules. |
| providers/agents/config/crds/agents.kedge.faros.sh_agentruns.yaml | Adds Kubernetes CRD for AgentRuns. |
| providers/agents/channels/channels.go | Adds outbound channel delivery helpers (telegram/slack/smtp). |
| providers/agents/assets.go | Adds embedded portal static asset serving wrapper. |
| providers/agents/apis/v1alpha1/types_trigger.go | Adds typed API for AgentTrigger. |
| providers/agents/apis/v1alpha1/types_schedule.go | Adds typed API for AgentSchedule. |
| providers/agents/apis/v1alpha1/types_run.go | Adds typed API for AgentRun and usage fields. |
| providers/agents/apis/v1alpha1/groupversion_info.go | Adds scheme registration for agents APIs. |
| providers/agents/apis/v1alpha1/doc.go | Adds package docs and kubebuilder group markers for agents APIs. |
| providers/agents/api/triggers.go | Adds HTTP handlers for triggers CRUD + run-now. |
| providers/agents/api/settings.go | Adds HTTP handlers for model credential CRUD (Secrets-backed). |
| providers/agents/api/schedules.go | Adds HTTP handlers for schedules CRUD + run-now. |
| providers/agents/api/run_test.go | Adds unit tests for budget enforcement logic. |
| providers/agents/api/inbox.go | Adds HTTP handlers for inbox list + resolve. |
| providers/agents/api/http.go | Adds identity extraction, tenant scoping, and GraphQL-backed tenant client acquisition. |
| providers/agents/api/http_test.go | Adds tests for tenant-path parsing. |
| .claude/settings.json | Expands Claude tool permissions allowlist and keeps additionalDirectories. |
Files not reviewed (3)
- providers/agents/apis/v1alpha1/zz_generated.deepcopy.go: Generated file
- providers/agents/portal/package-lock.json: Generated file
- providers/databricks/portal/package-lock.json: Generated file
Comments suppressed due to low confidence (1)
providers/databricks/portal/package-lock.json:612
- The lockfile entries for Rollup’s linux platform binaries no longer include the
libcselector. Because the Databricks portal is built in node:22-alpine (musl), removinglibcmakes npm unable to reliably choose the correct gnu vs musl optional dependency, which can breaknpm install/npm run buildin the Dockerfile.
Comment on lines
+596
to
+601
| if pt == "container" || pt == "docker" { | ||
| info.ImageRepository = "ghcr.io/" + strings.ToLower(org) + "/" + strings.ToLower(p.GetName()) | ||
| if versions, err := listPackageVersions(ctx, c, org, pt, p.GetName()); err == nil { | ||
| info.Versions = versions | ||
| } | ||
| } |
Comment on lines
+106
to
+113
| // jobLogTail downloads a job's logs (bounded) and returns the last maxLines, | ||
| // best-effort — a log fetch failure yields "". | ||
| func jobLogTail(ctx context.Context, c *gogithub.Client, org, repo string, jobID int64, maxLines int) string { | ||
| if maxLines <= 0 { | ||
| maxLines = workflowJobLogDefaultLines | ||
| } | ||
| logURL, _, err := c.Actions.GetWorkflowJobLogs(ctx, org, repo, jobID, 3) | ||
| if err != nil || logURL == nil { |
…ecret finalizer cleanup - infra: the application secret-bridge controller now finalizer-guards the registry pull Secret + its default-SA imagePullSecrets entry, cleaning both on instance delete (only instances that create the state carry the finalizer, so dev churn stays independent of the controller). - app-studio: remove the superseded deploy_project_runtime tool entirely — the Eino graph tool, spec, AppDeployment types (from the shared runtime-workflow input/result), and all wiring. Tests that used it as a runtime-tool example now use restart_runtime. Also folds in unrelated in-flight agents-provider working-tree changes per the author's request. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the App Studio dev→build→launch loop end-to-end, plus every fix the live testing surfaced.
The loop
sha-<commit>+latest).PackageCRs (tags + digests + imageRepository).<project>-prodinstance of the same template running the built digests.By provider
app-studio —
imageInputon template dev components; per-componentbuild.json+ matrix workflow (build+push only); build status + promote read ghcrPackageCRs;promote_project+POST /promote+GET /promotion+ Publish & Promote portal tab; build-doctor tools (check_project_build,get_build_logs,rebuild_project);ensureProjectRegistryPullSecretmints a ghcr dockerconfigjson from the connection token.code —
Packagepipeline carries per-version tags/digests + imageRepository;WorkflowRunReader/Dispatcherbackend caps +RepositoryBuildStatusCR/controller +build_status/rebuildMCP tools; OAuth now requestsworkflowscope (required to commit.github/workflows/*).infra — the application secret-bridge controller also bridges
<instance>-registryinto the runtime namespace + attaches it to the default ServiceAccount (covers all templates, wired once).Fixes surfaced by live testing (meme-forge-studio)
workflowscope (was 404 on committing the workflow).promoteProjectmust provision the artifact (production) environment —reconcileProjectLiveBindingsonly handledlive, so the instance was never created.Validated live
Build → Actions → Railpack → image in ghcr and promote → correct prod binding + prod Deployment are proven against a real repo. Remaining unproven link: the private-image pull secret end-to-end (this code path is untested at runtime).
deploy_project_runtimeis prompt-retired but its machinery isn't fully removed (harmless).🤖 Generated with Claude Code