Application Delivery — Overview

End-to-end view of how an application moves from a developer's laptop, through GitLab, a build path, image registry, and GitOps overlay patch, onto a spoke OpenShift workload cluster.

This section documents how an application repository becomes a running pod on spoke-dc-v6. Read this overview first; the rest of the section breaks the steps apart and details the contracts each step is required to honour.

The audience is anyone shipping or operating an application on the v6 fleet: developers, CI/CD maintainers, platform admins reviewing tenant onboarding, and auditors walking a release. Cross-link to the platform-side details (cluster, GitOps engine, Vault, Nexus, RHACS) under sections 2 and 5.

What “application delivery” means here

A request travels through six logical hops and one fixed shape of evidence. The hops are: source -> build -> scan -> image registry -> GitOps repo -> spoke Argo -> workload. The contract that connects them is digest-pinned: every successful build produces one immutable sha256:<64hex> digest, that digest is what gets written into Git, and the same digest is what runs in every environment.

The platform deliberately supports two build paths and one consume contract:

LayerPath A (Jenkins)Path B (Tekton)
Where the build runsjenkins-0 VM + jenkins-agent-0 agentopenshift-pipelines namespace on spoke-dc-v6
TriggerGitLab push webhook -> Jenkins notifyCommitGitLab push webhook -> Tekton EventListener
Build toolpodman / buildah on the agentbuildah Task in a per-build pod
ScanTrivy server (shared VM)Trivy server (same VM)
Image push targetapp-registry.apps.sub.comptech-lab.com (Nexus)quay.apps.sub.comptech-lab.com (Quay) or Nexus fallback
Overlay patchupdate-overlay-digest.sh from Jenkins agentupdate-overlay-digest Tekton Task
Evidence targetMinIO developer-ci-evidence bucketMinIO developer-ci-evidence bucket
ApplicationSet generatorunchangedunchanged

Both paths land at the same digest patch on apps/<team>/<app>/overlays/dev/kustomization.yaml, and Argo CD cannot tell which path produced a given commit. That symmetry is the design centre of this section.

Whiteboard: the end-to-end flow

Reading the diagram from left to right:

  1. Developer pushes to a feature branch (or to main for trusted maintainers) in their division’s GitLab project under divisions/<division>/<repo>.
  2. GitLab webhook fires at the LAN endpoint of the build path. Path A uses the Jenkins Git plugin notifyCommit URL; Path B uses a Tekton EventListener Route. Both validate an HMAC secret to keep the trigger surface from being abused.
  3. The build path clones the source, compiles and tests, and assembles a container image. Tool versions for the Jenkins agent: Podman 4.9.3, Buildah 1.33.7, Skopeo 1.13.3, Trivy 0.70.0. Tekton uses the OpenShift Pipelines distribution of those same tools through Tasks.
  4. Trivy scans the built image in server mode against the shared Trivy VM. The severity policy is fail on CRITICAL, warn on HIGH, identical for both paths so promotion semantics do not depend on which path produced the image.
  5. The image is pushed to either Nexus app-registry (Path A) or Quay (Path B). The push response carries the manifest digest; that digest is captured and used everywhere downstream.
  6. CI evidence (build.log, sbom.spdx.json, trivy-scan.json, image-digest.txt) is uploaded to MinIO under developer-ci-evidence/<team>/<app>/<git-sha>/. The schema is the same regardless of which path produced the build.
  7. An MR is opened against the division’s GitOps repo (<division>-gitops). The MR contains a single change: the digest: field under images: in apps/<team>/<app>/overlays/dev/kustomization.yaml. No other file changes. Merge into main is gated by approval (one approver for non-production, two for production-impacting paths).
  8. Hub Argo CD on hub-dc-v6 runs the app-tenants ApplicationSet. The Git directory generator scans apps/<team>/<app>/overlays/*/kustomization.yaml, produces one Argo Application per overlay, and (in the v6 pull model from ADR 0018) ships each as a ManifestWork to the target spoke.
  9. Spoke Argo CD on spoke-dc-v6 pulls its ManifestWork, applies the rendered Kustomize output to the local API server, and the kubelet pulls the image strictly by digest from the registry referenced in the overlay.

Steps 8 and 9 are the pull-model boundary: the hub never opens a TCP connection toward the spoke’s API server. The spoke’s klusterlet maintains the only long-running session, initiated outbound. See RHACM and OpenShift GitOps for the architectural background.

What lives where

SystemHostname (public route)Internal LAN endpointRole in the flow
GitLab CE 18.11.1gitlab.apps.sub.comptech-lab.comLAN endpoint on the GitLab VMSource repos, webhooks, MRs, approvals
Jenkins 2.555.1jenkins.apps.sub.comptech-lab.comLAN endpoint on the Jenkins VMPath A build controller
Jenkins agentn/a (private)LAN endpoint on the Jenkins agent VMPath A build executor, developer-build label
OpenShift Pipelines (Tekton)served on spoke-dc-v6openshift-pipelines namespacePath B build pipelines
Trivy servertrivy.apps.sub.comptech-lab.comLAN endpoint on the Trivy VMShared scan gate, both paths
Nexusnexus-mirror.apps.sub.comptech-lab.comLAN endpoint on the Nexus VMApp image pushes (Path A) + base image pulls
Nexus app-registryapp-registry.apps.sub.comptech-lab.comTLS-fronted by HAProxyPath A push target
Nexus docker-groupdocker-group.apps.sub.comptech-lab.comTLS-fronted by HAProxyBase image pulls (both paths)
Quayquay.apps.sub.comptech-lab.comserved from spoke-dc-v6Path B push target
MinIOn/a (private API)LAN endpoint on the MinIO VMCI evidence bucket developer-ci-evidence
OpenShift hub*.apps.hub-dc-v6.sub.comptech-lab.comserved from hub-dc-v6Hub Argo, ACM, ApplicationSet
OpenShift spoke*.apps.spoke-dc-v6.sub.comptech-lab.comserved from spoke-dc-v6Spoke Argo, tenant workloads

Internal-only specifics (IP addresses, private DNS aliases, runner tokens, robot credentials) are kept in opp-full-plat/connection-details/.

The contracts that hold the chain together

The chain is brittle if any one contract drifts. Five contracts are codified in source-of-truth files:

ContractSourceOwns
App-repo overlay layoutconnection-details/app-repo-contract.md (DEV-OCP-2.1, #182)apps/<team>/<app>/{base,overlays} shape, what CI may modify
Image-tag -> digest conventionconnection-details/image-digest-overlay.md (#185)The images: block format in every overlay
Build-once / promote-by-digestconnection-details/promotion-model.md (#184)How dev -> stg -> prd promotion works
CI evidence schemaconnection-details/ci-evidence-schema.md (#195)What keys land in MinIO per build, required vs optional
Image registry allowlistconnection-details/image-registry-allowlist.md (#186)Which registries the spoke accepts at admission

Drift in any one of them surfaces as a downstream failure that looks unrelated at first glance: an overlay missing images: block fails the Jenkins overlay-patch step (#188 symptom: ERROR: no 'digest: sha256:<64-hex>' line found); a registry not in the allowlist passes the build and pull but is denied by the VAP (allowed-image-registries) at pod create. The pattern is always the same shape of failure - the chain’s invariants stop holding.

What the platform deliberately does not do

A few things are not part of application delivery in this lab; they belong to neighbouring sections:

  • Cluster provisioning and tenant guardrails. Namespaces, AppProjects, quotas, RBAC, NetworkPolicies, ResourceQuota, LimitRange, PodSecurity labels — owned by openshift-platform-gitops (Section 5). Tenants do not register their own namespaces.
  • Secret content delivery. The build path may know the name of a Secret to reference, never its bytes. All app secrets come from Vault via ExternalSecrets (Section 2.4); ConfigMaps and Secret data are not committed.
  • VM-hosted tools’ own configuration. GitLab, Jenkins, Nexus, HAProxy, PowerDNS, Vault, Trivy, MinIO live under vm-platform-ops (Section 3), not in any application repo and not in openshift-platform-gitops.
  • Direct oc apply from a build job. Build paths write Git, not the API server. The only path the API server accepts changes on for tenant workloads is the Argo sync.

Glossary used in this section

TermMeaning
App repodivisions/<division>/<repo> or divisions/<division>/<division>-apps-monorepo — the application source.
App GitOps repodivisions/<division>/<division>-gitops — the overlay tree Argo reconciles.
Platform GitOps repocomptech-platform/openshift-ops/openshift-platform-gitops — cluster desired state. App teams do not have write access.
Path AJenkins build path on the Jenkins VM + agent. Pushes to Nexus app-registry.
Path BTekton build path on spoke-dc-v6 (OpenShift Pipelines). Pushes to Quay (or Nexus fallback).
Digest patchThe single-line change in images: that updates digest: to the new sha256:....
OverlayOne subdirectory under apps/<team>/<app>/overlays/<env>/ (dev, stg, prd).
AppProjectPer-tenant Argo CD scoping object — allowed source repos, namespaces, kinds. Authored in openshift-platform-gitops.
ApplicationSetThe hub-side controller that generates one Application per overlay directory.
  • The federated GitLab side. Section 02-federated-gitlab covers the repo layout, role groups, runner classes, and branching conventions that make CI behave consistently across divisions.
  • The build paths in detail. Section 03-build-paths walks Path A (Jenkins) and Path B (Tekton) end-to-end with stage tables, decision matrix, and the overlay patch mechanics.
  • The GitOps consume side. Section 04-gitops-consume describes how the ApplicationSet, AppProjects, and per-cluster admission policies turn an overlay into a pod.
  • Tenant onboarding and golden-path samples. Sections 05 and 06 are the “how do I actually onboard” runbook with copy-paste sample apps.

References

  • connection-details/gitlab-operator-guide.md (FG-1 operator handoff, #128)
  • connection-details/app-repo-contract.md (#182, DEV-OCP-2.1)
  • connection-details/image-digest-overlay.md (#185, DEV-OCP-2.4)
  • connection-details/promotion-model.md (#184, DEV-OCP-2.3)
  • connection-details/build-path-matrix.md (#194, DEV-OCP-3.6)
  • connection-details/ci-evidence-schema.md (#195, DEV-OCP-3.7)
  • connection-details/image-registry-allowlist.md (#186, DEV-OCP-2.5)
  • connection-details/jenkins-ocp-path.md (#187/#188, DEV-OCP-3A.1/3A.2)
  • adr/0015-federated-gitops-repo-architecture.md
  • adr/0018-acm-openshift-gitops-pull-model-v6.md
  • adr/0019-nexus-only-image-supply-chain.md
  • adr/0023-federated-gitlab-group-repo-ownership.md
  • DEV-OCP closed issues under milestone #32 (especially #173, #174, #182-#195)

Last reviewed: 2026-05-11