Skip to main content
TruStacks
← All posts

TruStacks works on Azure DevOps. Keep your repos and your pipelines

TruStacks4 min read

TruStacks connects to Azure Repos as a git host and writes Azure Pipelines as your CI. A personal access token is delivered sealed to your runner and never stored by TruStacks. The crew reads your service repos, writes an Azure Pipelines extends template with tasks pinned to full versions and containers pinned by digest, checks it against the signed policy before the pull request opens, and a named human merges. The integration is checked against Microsoft's documented API and YAML, and is ready for teams on Azure DevOps to test in their own organization.

TruStacks now works on Azure DevOps. Azure Repos connects as your git host, and when your Stack file names Azure Pipelines as your CI, the crew writes Azure Pipelines instead of GitHub Actions workflows. Everything else stays the same: the crew reads your service repos, the change is checked against the signed policy before a pull request opens, and a named person on your team merges it. Nothing about the governance changes because the tooling did.

Why Azure DevOps

A client of ours runs most of its delivery on Azure DevOps. Teams like that have their repos are in Azure Repos, their pipelines in Azure Pipelines, and their approvals and branch policies are already set up there. Asking them to move to GitHub to get governed AI delivery would be asking them to rebuild the controls they already trust.

So we did it the other way around. The git host and the CI system are pluggable. The practice rules and the policy check are not.

The git host and the CI system are interchangeable; the check is not. Git hosts: GitHub, through the TruStacks GitHub App, or Azure Repos, with a personal access token sealed to your runner. CI systems: GitHub Actions, as a reusable workflow per service, or Azure Pipelines, as an extends template per service plus the caller. Whichever pair you run, the same things hold: the same test and lint commands for your framework, steps pinned to explicit versions, the signed constitution and your overlay checked before the pull request opens, and a named human merges.

Your git host

  • GitHub

    Through the TruStacks GitHub App.

  • Azure ReposNew

    With a personal access token, sealed to your runner.

The same either way

  • The same test and lint commands for your framework
  • Steps pinned to explicit versions
  • The signed constitution and your overlay, checked before the pull request opens
  • A named human merges

Your CI

  • GitHub Actions

    A reusable workflow per service.

  • Azure PipelinesNew

    An extends template per service, plus the caller.

Azure Repos with GitHub Actions works. GitHub with Azure Pipelines works. The test and lint commands for your framework, the pinning rules, the signed constitution, and your own overlay rules are the same whichever pair you run.

Azure Repos: your token stays in your cluster

You connect Azure Repos with a personal access token you create, scoped to the one organization the repo lives in, with Code (Read & write) and Build (Read). A repo TruStacks only reads needs Code (Read).

What happens to that token is the part a security team will ask about:

  • The control plane hands it to your runner sealed, so only your runner can open it.
  • Your runner checks it with one read-only call to the repository.
  • If the check passes, the runner writes it to a Secret in its own namespace.

TruStacks keeps only whether the token works. The token itself is never stored in the TruStacks database. When you replace it, the old one keeps working until the new one passes the same check.

TruStacks never merges, never creates tags, never force pushes, and never changes branch policies. Your runner watches the platform repo and records who completed each pull request and who voted to approve it. If the approvals can't be read, the merge is recorded as approver not recorded, never as nobody approved.

Azure Pipelines: an extends template, pinned

When your CI is Azure Pipelines, the crew writes an extends template for each service in your platform repo, and the pull request gives you the short caller file to add to the service repo. Microsoft recommends extends templates for the most secure pipelines, and only extends works with the Required template check. Turn that check on for your registry connection and your prod environment, and a pipeline that doesn't use the template can't push an image or deploy.

Pinning is explicit about what it does and does not guarantee:

  • The template is pinned to a platform-repo commit, so it can't change without a reviewed change.
  • Built-in tasks are pinned to a full version from a short allowlist. That is version-pinned, not immutable, and the docs say so.
  • Everything else runs in a container pinned by digest.
  • Marketplace tasks are never used.

What the check can see, and what it can't

This is the part we would rather be precise about than impressive. The policy check reads the files TruStacks wrote. Some of what makes a pipeline safe is in those files. Some of it is a setting in Azure DevOps that no file shows.

What the TruStacks policy check verifies from the pipeline files it wrote: A job runs the framework's test command; A job runs the lint command; Tasks are allowlisted, at a full version; Containers are pinned by digest; A prod deploy job names an environment; No GitHub Actions files on an Azure proposal, and the reverse. What it cannot see, because it lives in the platform's settings rather than in any file: Approvals and checks on environments; Required template checks; Branch policies and required reviewers; Job authorization scope and repository protection; Tag permissions; Whether the pipeline is registered or has run. A proposal passing the check says nothing about the second list. Where TruStacks can read those settings, it reports them as observed, never as verified.

Verified from the pipeline files

  • A job runs the framework's test command
  • A job runs the lint command
  • Tasks are allowlisted, at a full version
  • Containers are pinned by digest
  • A prod deploy job names an environment
  • No GitHub Actions files on an Azure proposal, and the reverse

Settings in Azure DevOps, not in any file

  • Approvals and checks on environments
  • Required template checks
  • Branch policies and required reviewers
  • Job authorization scope and repository protection
  • Tag permissions
  • Whether the pipeline is registered or has run

A proposal that passes says nothing about the settings list. Where TruStacks can read those settings, it reports them as observed, never as verified.

A proposal passing the check says nothing about the settings list. That is why every Azure Pipelines pull request carries a checklist for the settings YAML can't hold: registering the pipeline, a registry connection with workload identity federation, Required template checks, approvals on the prod environment, and disabling Marketplace tasks. Where TruStacks can read those settings, it reports them as observed, never as verified.

Try it

We have checked the integration against Microsoft's documented API responses and YAML. We have not yet run it in a live Azure DevOps organization, so if you run on Azure DevOps, your first connection is exactly what we are asking for. Tell us what you see.

Azure DevOps Server (on-premises) is not supported. The Beta is open; see pricing to get started.

Agents propose. Policy decides. Humans approve.

  • Azure DevOps
  • Azure Pipelines
  • AI delivery governance
  • platform engineering

See it open a pull request.

The crew reads a real repository and proposes a policy-checked pull request you review yourself. The hosted Beta is open to the first 50 teams. Sign up with the Beta link and it's free for 45 days, with no card needed. The hosted quickstart walks you to your first governed pull request.