Skip to Content
WorkshopsCI/CD generation (local dev)

CI/CD generation workshop

A guided walkthrough of one full crew run: the Code Reviewer reads a service repo, the DevOps Engineer drafts a CI workflow and deploy artifacts, the artifacts are validated and judged by the policy gate, a pull request opens, and a gap analysis scores the result.

The point is not just to make a PR happen. It is to see what each agent does, why, and where the trust boundaries are: agents propose, policy decides, humans approve.

⚠️

This workshop needs a local development environment. It uses the seeded sample repos, the in-cluster Gitea and ArgoCD, and the trustacks CLI, which talks to a local or self-hosted control plane (the CLI sends no credentials, so it cannot drive the hosted service). Set up with Local development first.

On the hosted product? You can follow most of it in the app against your own repos. Steps 2, 3 and 5 are app screens; for steps 1 and 4 use Run analysis and Promote to proposal on the service; for step 6, promote without dry run and the pull request opens in your GitHub platform repo; for step 8, merge there and sync in your own ArgoCD; step 9 is in the app. Step 7 needs an overlay bundle, which hosted runners cannot load yet. The product guide covers each screen.

What you will learn

  • How the Code Reviewer identifies a framework, and why known frameworks are detected deterministically before the agent runs.
  • What the DevOps Engineer reads before it writes (read-and-preserve).
  • The two checks before any PR: artifact validation, then the policy gate.
  • What a TruStacks pull request tells its reviewer.
  • What a gap analysis and maturity score look like for the sample stack.

Time required

About 45 minutes. Each crew run takes a minute or two; most of the time is reading what the agents produced.

Setup

Bring up the local stack and seed it, as described in Local development:

make up make seed make urls # every service reachable on *.localtest.me:8080

make seed creates four sample service repos in Gitea (FastAPI, Spring Boot, .NET and Go), a platform repo, an overlay repo, the matching connection profiles, and a polyglot-demo Application that binds the four samples to the platform repo. This workshop uses the FastAPI sample, whose profile is named sample-app-gitea.

Open http://ui.localtest.me:8080. You should see the app with the sidebar (Overview, Get set up, Workspace, Signals, Applications, …).

Walkthrough

Step 1. Run the Code Reviewer from the CLI

cd runner && uv sync uv run trustacks review sample-app-gitea

The CLI streams the run’s events live. The shape:

started → cloned → framework_detected (python_fastapi) → tool_call / tool_result (the agent reading files) ×N → finding ×N → done

What is happening: before the agent starts, a deterministic detector matches the repo against TruStacks’ framework packs (here, fastapi in pyproject.toml). The agent is told the framework as a fact, so it does not guess. It then reads files with a small, explicit set of tools, and submits a typed RepositoryAnalysis. Each tool_call is the agent asking to read something; each tool_result is the answer.

Note the analysis id at the top of the output, and keep it in a shell variable for the next steps:

read -r -p "Analysis id printed above: " ANALYSIS_ID

Step 2. See the same run in the app

Go to Applications → View all services across applications, open sample-app-gitea, and look at the Analyses tab. Your CLI run is there. open → shows the same events as an Activity log, with the Coordinator narrating and the Code Reviewer’s tool calls attributed to it. When the run is done, the Repository Analysis card shows framework, language, package manager, runtime version, entrypoints, and whether tests, a Dockerfile and CI exist.

You can start an analysis from here too: Run analysis with ref main.

Step 3. Look at the declared stack

Open Stack. This is the environment profile the agents read: the environment-profile.yaml in the seeded overlay repo. Note which tooling categories are declared (CI platform, GitOps controller) and which are not. Only declared tools will get pipeline steps in the next step. The agents never add a tool you did not declare; recommendations go into the gap analysis instead.

Step 4. Promote the analysis to a proposal

From the CLI, with a dry run first:

uv run trustacks plan "$ANALYSIS_ID" --dry-run

Or in the app: on the service’s Analyses tab, promote →, tick dry-run (skip PR), then Promote (dry-run).

The event shape:

started → cloned_app → cloned_platform → analysis_done → profile_loaded → agent_started (DevOps Engineer) → tool_call read_file (repo="platform") ×N read-and-preserve → artifact_emitted ×N → proposal_built → artifact_validation does it render and parse? → policy_check (allow | deny) the gate → gap_check (advisory) → dry_run_skipped → done

Watch for three things:

  • The platform repo is read first. The DevOps Engineer reads the current version of each file it is about to write. On a first proposal, nothing exists yet and it emits fresh files.
  • Validation runs before policy. Helm (or Kustomize) must render, workflows must parse, names must be legal Kubernetes names. If anything fails, or a check could not run, the run stops here.
  • The Constitution speaks last. policy_check is OPA evaluating the proposal against the constitution and the overlay. On the proposal page it reads clean, no violations, or denied with the rule ids.

Step 5. Read the proposal

Open the proposal (the CLI prints its id; the app navigates there). Below the timeline:

  • Explanation: summary, blast radius, rollback, rules cited, and which profile entries were used.
  • Files: one tab per emitted file. Expect a reusable CI workflow (.github/workflows/ci-<service>.yaml, on: workflow_call only), a minimal Helm chart (Chart.yaml, values.yaml, a Deployment and a Service) under gitops/<application>/<cluster>/<service>/, and an ArgoCD Application under argo-apps/.

Look at the workflow’s uses: lines. Every one is pinned to a 40-character commit SHA taken from a TruStacks-curated pack. An action that is not in a pack is left out and recorded as a TODO, never guessed.

Step 6. Open the real pull request

Run it again without dry run:

uv run trustacks plan "$ANALYSIS_ID"

The run ends with pr_opened and a link to the PR in Gitea. The PR body carries the reviewer’s context: Summary, Blast radius, Rollback, Rule citations, EnvironmentProfile entries used, any Preservation notes and Files removed, and the file list. The structure exists so a reviewer can answer why was this proposed, and what does it touch? before reading the diff.

If the platform repo already matches the proposal exactly, the run ends with “nothing to change” instead of opening a duplicate PR.

Step 7. See a deny

The easiest way to watch the gate refuse something is to add a rule that the emitted workflow will not satisfy. The policy authoring workshop does exactly that: a rule requiring top-level permissions: on every workflow. After landing it, re-run Step 4. policy_check reports denied, cites your rule id, and no PR opens. The Overview’s Policy in force card starts counting it.

⚠️

Remove the rule before Step 8. Step 8 promotes the same analysis again, and with your rule still loaded that proposal is denied too. Delete the rule’s directory from your overlay repo, run trustacks rule sign again to publish the overlay without it, and restart the runner (kubectl -n trustacks-system rollout restart deployment runner-runner). Or do Step 8 first and come back to this step.

Step 8. Review, merge, and see read-and-preserve

Merge the PR in Gitea. In local development, make seed has already pointed the in-cluster ArgoCD at the platform repo; open http://argocd.localtest.me:8080 to see the new Application. (Building and loading the sample image for an actual running pod is covered in the project’s workshop guide under Close the deploy loop.)

Now edit the generated workflow in Gitea (add a harmless step, for example an echo in its own step) and merge that edit. Promote the same analysis again. In the new PR:

  • your added step is still there, because the DevOps Engineer read the file before re-emitting it;
  • a Preservation notes section says what it kept and why.

Step 9. Score it

In the app, open Gap analyses and Run new gap analysis (or type /gaps in the Activity chat at #/activity). Watch the Coordinator consult Baseline Security and SOC2, each replying in its own voice.

Then open Maturity. You will see a tier, a bar split into verified, credited and potential, and the open gaps. Note that the score is computed deterministically by the runner from your profile and the rules; the language model writes the prose, not the number. See Verified, claimed and disputed.

What you should take away

  • The gate is policy, not the agent’s judgement. Validation and OPA decide whether a proposal can become a PR.
  • The environment profile is the platform’s memory. Change it, and the next proposal changes.
  • The PR is the hand-off. Everything before the merge is agents proposing. The merge is a human committing. ArgoCD deploys.
  • Re-runs are safe. Read-and-preserve keeps your team’s edits.

Where to go next

Last updated on