Dapr workflow orchestration for infrastructure automation — golden image builds, provisioning, and more.
This repository contains Dapr durable workflows that orchestrate infrastructure automation tasks. Workflows run as Go services on Kubernetes with Dapr sidecar injection, calling Dagger modules as building blocks.
| Workflow | Description | Status |
|---|---|---|
| golden-image-build | Render → packer build → test VM → promote golden image | Planned |
| backstage-template-execution | Trigger Backstage scaffolder templates, poll the task to completion, optionally watch a follow-up GitHub Actions run, and auto-merge the resulting PR | Working |
| cluster-build-watch | Watch a cluster build from the GitOps sync (Argo CD / Flux) through the Crossplane XR's status.stage to Ready; report every checkpoint and every stuck stage to a status ConfigMap, Teams and a CloudEvent webhook |
Prototype |
End-to-end orchestration around a Backstage scaffolder template:
- POST to
/api/scaffolder/v2/tasks(or/dry-run) to start the template - Poll the scaffolder task until it reaches
completed/failed/cancelled - Optionally poll a GitHub Actions workflow run on a deterministic branch (the activity skips runs that completed with conclusion
skipped, e.g. PRs that fired before labels were applied) - Optionally squash/merge/rebase-merge the PR once the GH run reaches
success
Inputs are passed as JSON; the worker reads GITHUB_TOKEN from its environment for the GH-watch + merge activities. See backstage-template-execution/input.json (create flow) and backstage-template-execution/input-delete.json (delete flow) for examples wired against the create-terraform-vm and delete-terraform-vm Backstage templates.
cd backstage-template-execution
export DAPR_SERVICE_TOKEN=... # Backstage scaffolder token
export GITHUB_TOKEN=... # PAT with repo scope (actions:read + pull_requests:write)
dapr run --app-id backstage-tpl --dapr-http-port 3500 -- go run .
# in another terminal
./run.sh # uses input.json
./run.sh input-delete.json
./run.sh status <id>Every push to main that touches workflows/** runs
.github/workflows/build-scan-changed.yaml: gosec → ko-build → trivy against
ttl.sh, then a release job that publishes to ghcr.
| Artifact | Repo | Tag |
|---|---|---|
| Container image | ghcr.io/stuttgart-things/dapr-<workflow-dir> |
12-char commit SHA |
| Kustomize base (KCL deploy dirs only) | ghcr.io/stuttgart-things/dapr-<workflow-dir>-kustomize |
the same 12-char SHA |
Two things are deliberate:
- The released image is the one Trivy scanned — the release job copies the
already-built
ttl.shimage with crane instead of rebuilding it. - Both artifacts carry the same tag, and the kustomize base is rendered with
that tag injected into the Deployment. Pulling artifact
<sha>therefore cannot hand you manifests pointing at a different image. The flux bundle underapps/dapr/components/template-executionpins both (DAPR_BACKSTAGE_TPL_IMAGE_TAG,DAPR_BACKSTAGE_TPL_VERSION).
There is no moving latest tag. Pin the SHA in flux, reconcile, and check the
running pod's image.
Taskfile.yaml remains local-only: it pushes to ttl.sh, which expires and is
not reachable from a cluster.
wget -q https://raw.githubusercontent.com/dapr/cli/master/install/install.sh -O - | /bin/bash
dapr initSee docs/setup/dapr-cli.md for details.
Patrick Hermann, stuttgart-things (2025-2026)
Licensed under the Apache License 2.0.