Skip to content
Coops IT Services
  • CI/CD
  • DevSecOps
  • Governance

What Good CI/CD Governance Looks Like

A practical approach to combining central delivery controls with the autonomy engineering teams need to ship and operate software.

5 min read

CI/CD governance is sometimes framed as a choice between central control and developer autonomy. That framing leads to predictable failure modes. With no shared controls, teams repeat security and delivery mistakes. With too much central control, the platform becomes a ticket queue and developers learn to work around it.

Good governance establishes a small number of dependable boundaries, provides supported ways to work inside them, and makes exceptions visible. It treats the delivery platform as a product rather than a collection of mandatory YAML fragments.

Govern outcomes before implementation details

A useful control begins with the outcome it protects. Examples include:

  • production artefacts are traceable to reviewed source;
  • high-severity security findings receive an explicit decision;
  • credentials are not embedded in pipeline configuration;
  • deployment to a protected environment is appropriately authorised;
  • the same tested artefact is promoted between environments.

These statements leave room for technical design. A rule such as “every repository must contain these 200 lines of pipeline YAML” governs an implementation and quickly becomes brittle.

Translate each outcome into a control owner, scope, enforcement point, evidence and exception process. If one of those is missing, the control will be difficult to operate.

Put controls at the right layer

Not every requirement belongs in the application pipeline. Some controls are stronger and simpler at the platform or environment boundary.

Layer Suitable responsibilities
Platform Identity, protected resources, runner trust and policy enforcement
Shared pipeline Supported build, test, scan and packaging components
Application project Workload-specific tests, dependencies and deployment intent
Deployment platform Environment admission, configuration reconciliation and runtime policy

For example, a reusable pipeline component can provide a supported container build. A centrally managed policy can ensure a security job is not omitted. The application project still owns its test strategy and service-specific configuration. Argo CD or another deployment layer can enforce what reaches a protected cluster.

Choosing the correct layer avoids duplicating a control in every repository and reduces the incentive to create complex pipeline logic.

Use policy-as-code carefully

Policy-as-code brings version control, review and repeatability to governance. It also makes a mistake repeatable at scale.

Central policies should follow normal engineering practice: small changes, peer review, automated validation, a staging path and clear ownership. Test both policy syntax and resulting platform behaviour. A valid rule that targets the wrong namespace is still a failed control.

Keep policy repositories understandable. Organise rules by purpose, describe scope near the definition, and link to the control intent. Avoid a single file that mixes unrelated approvals, scan execution and pipeline injection logic.

Policy versioning needs care. Pinning application projects permanently to old policy defeats central improvement, while changing every project at once increases blast radius. Use staged scope or a controlled rollout mechanism where the platform supports it.

Build reusable pipeline components

Reusable components are the practical side of governance. They turn the preferred path into the easiest path.

A strong component has a narrow purpose, documented inputs, stable outputs and sensible defaults. It should expose the choices teams genuinely need without making every internal command configurable. Components for building containers, publishing artefacts or running standard scanners are good candidates.

Treat them like products:

  1. publish versioned releases;
  2. provide a minimal working example;
  3. test common and failure paths;
  4. document runtime and permission assumptions;
  5. publish migration notes for breaking changes.

Do not force every workload through one giant template. A Java service, infrastructure repository and embedded build have different needs. A small catalogue of composable components is easier to evolve than a universal pipeline.

Make security controls explainable

A developer should be able to understand why a pipeline or merge is blocked, which evidence caused it and what action is available. A technically correct control with an opaque failure message creates avoidable operational load.

Security scanning needs a defined response model. State which findings block, who can accept risk, how false positives are managed and when an exception expires. Separate the scanner’s output from the organisation’s decision policy.

Controls should also fail safely when their dependencies are unavailable. Decide whether a scanner outage blocks all delivery, allows a time-bounded exception or triggers another mechanism. The answer may vary by service criticality and environment, but it should not be improvised during an incident.

Design a real exception path

Exceptions are part of governance, not evidence that governance failed. Legacy workloads, urgent fixes and vendor constraints will create legitimate cases.

A workable exception records:

  • the control being bypassed;
  • the affected scope;
  • the reason and compensating measures;
  • the accountable approver;
  • an expiry or review date;
  • evidence that the exception was applied as approved.

Keep the route proportionate. If every exception needs a committee, teams will hide workarounds. If exceptions never expire, the control becomes optional. Automating reminders and expiry checks helps keep the process honest.

Test governance as a system

Unit tests for shared scripts are useful, but governance lives across project configuration, policies, runners, scanners and deployment platforms. Integration tests should create representative conditions and assert the resulting pipeline, approval or deployment behaviour.

Include negative scenarios: a project outside scope, an attempted override, a missing scan result and an expired exception. Publish machine-readable results such as JUnit reports so upgrade rehearsals and changes leave evidence.

Monitor the platform operationally as well. Useful indicators include policy evaluation failures, component adoption by version, exception age and central job reliability. Avoid turning these into vanity measures; use them to find friction and risk.

Governance is a maintained relationship

The best governance models are clear about what the organisation owns and what teams own. They give developers dependable building blocks, give security stakeholders trustworthy evidence and give platform teams a manageable service boundary.

Start with a few high-value outcomes. Place each control at the strongest practical layer, make the supported path easy, test the real behaviour and provide an explicit exception route. That creates governance capable of improving delivery instead of merely adding gates to it.

Continue reading

Related articles