RHELS LAB

Delivery

CI/CD & the supply chain

Status: partial — the pipeline builds, signs, and scans end-to-end. Digest pinning is blocked (run 36876895467) and Kyverno remains Audit, not Enforce.

Inside this chapter

  1. 1 · The jobs Follow your code from push to pod — each step of the chain is a door.
  2. 2 · How it works How apps ship today, what the signed pipeline adds, and the principle behind it.
  3. 3 · The evidence The flow diagram with its runs and commits — and what is still blocked, in the open.

Start here

The jobs this chain does for you

This is the journey your code takes — from a commit on your machine to a running pod on the floor, built, signed, and scanned on the way. Pick the step you came for.

Concepts

How the chain works, and why

How it ships today

  1. Push to Git

    Every change starts as a commit on the app repo.

  2. GitHub Actions — self-hosted runner

    The org runner on pro builds, signs, and scans the image (2026-11-01, lab-monorepo#102).

  3. Argo CD syncs to CRC

    OpenShift GitOps reconciles the app namespace from the IAC repo (current refs — signed digest pin is blocked).

Live · rhels/team#107

  1. Harbor registry

    Enterprise image registry on the tooling plane — the single place images live.

    rhels/team#107

  2. Cosign signing

    Keyless signing via GitHub OIDC — every image carries a verifiable signature.

    rhels/team#107 · run 36876895467 succeeded

  3. Trivy scanning

    Vulnerability scans gate promotion, not just report it.

    rhels/team#107 · run 36876895467 succeeded

  4. Kyverno verifyImages

    ClusterPolicy require-signed-images in app* namespaces is Audit, not Enforce. Unsigned images are reported, not rejected.

    GitOps c5d749f · validationFailureAction: Audit

Design principle

The design principle: nothing should reach the workload cluster unsigned. The digest in the IaC repo is not enough on its own — the image must also be signed (Cosign), scanned (Trivy), and admitted (Kyverno verifyImages) before a pod starts in any app* namespace. Kyverno audits today and enforces next; digest pinning is the other half of the #107 final mile (blocked on Actions run 36876895467; ClusterPolicy require-signed-images is Audit, not Enforce — unsigned images are not rejected).

Reference

The flow, as data

The chain as recorded in the inventory — every status below carries its evidence (a run, a commit), and the blocked steps are printed, not hidden.

End-to-end flow

  1. git push

    source

  2. GitHub Actions (self-hosted mini-k8s)

    build

  3. build + push to Harbor

    registry

  4. Cosign sign (keyless, GitHub OIDC)

    sign

  5. Trivy scan

    scan

  6. digest written to IAC repo

    pin

    blocked

  7. Argo CD syncs to CRC

    deploy

  8. Kyverno verifyImages in app* namespaces

    admit

    audit

  • rhels/team#107
  • rhels/local-k8s-gitops Actions run 36876895467 (headSha c5d749f586d43640a61591f0bcdb94ac04d98e0d) — failed at Pin digest in IAC repo after build/push, Cosign, and Trivy succeeded
  • GitOps main c5d749f586d43640a61591f0bcdb94ac04d98e0d clusters/crc/security/require-signed-images-policy.yaml — validationFailureAction: Audit (not Enforce)
  • blocked — digest written to IAC repo : failed at Pin digest in IAC repo — rhels/local-k8s-gitops Actions run 36876895467
  • audit — Kyverno verifyImages in app* namespaces : validationFailureAction: Audit (not Enforce) — GitOps c5d749f586d43640a61591f0bcdb94ac04d98e0d require-signed-images-policy.yaml

Next chapter

4. Observability

Shipping is only half the story. Next, the watchtower: how the lab sees what it ships.