Skill v1.0.1
currentAutomated scan100/100+3 new
version: "1.0.1" name: ci-cd-quirks description: Use when CI checks fail unexpectedly, when preparing code for CI, or when encountering non-obvious build and pipeline behavior. Covers vendoring, hermetic builds, security scans, code generation checks, coverage, and webhook validation gotchas.
CI/CD Quirks and Gotchas
Overview
Integration-service CI runs on Konflux (Tekton-based) for builds and GitHub Actions for linting/testing. Several non-obvious requirements catch developers off guard.
When to Use
- CI failed and you don't understand why
- Preparing a change that touches dependencies, CRDs, or RBAC
- Understanding what the build pipeline actually does
- Debugging webhook validation behavior
Must-Run Commands Before Push
| When you changed... | Run this | Why | |
|---|---|---|---|
Any go.mod / go.sum | go mod tidy && go mod vendor | Vendor dir is committed; CI fails on drift | |
Types in api/v1beta2/ | make generate manifests | DeepCopy and CRD/RBAC manifests must be in sync | |
Any .go file | make fmt | CI fails on uncommitted gofmt changes | |
+kubebuilder:rbac markers | make manifests | RBAC ClusterRole must reflect markers |
CI Checks That Surprise People
Vendoring (most common failure)
Go vendoring prunes non-Go files. After go mod vendor, CRD YAML files from dependencies are gone. make download-crds re-downloads them for tests. CI runs this automatically, but if you updated deps and didn't vendor, CI fails.
RBAC Wildcard Check
CI greps config/ for RBAC wildcards (*) and fails if found. Never use wildcard verbs or resource names in +kubebuilder:rbac markers.
Code Generation Drift
CI runs make generate manifests and diffs the result. Any uncommitted generated files = failure. Always commit generated output.
Cached Client list/watch RBAC Requirement
The controller-runtime cached client requires list and watch verbs on every resource type served from the informer cache — omitting them causes a reflector retry storm. Resources in Client.Cache.DisableFor (currently Secret and konfluxv1alpha1.Component — see cmd/main.go) bypass the cache and do not need these verbs; the old appstudio.redhat.com Component type is not in DisableFor and still uses the cache. CI will not catch this: envtest runs as cluster-admin and the RBAC check only looks for wildcards, so the bug surfaces only under real RBAC in a production cluster.
go mod tidy Drift
CI runs go mod tidy and checks for changes. If your go.mod/go.sum differ after tidy, CI fails.
Build Pipeline Details
PR Pipeline (.tekton/integration-service-pull-request.yaml)
- Injects
ENABLE_COVERAGE=true— binary built with-cover -covermode=atomic -tags=coverage - Hermetic build (network-isolated), deps prefetched via Cachi2
- Multi-platform: x86_64 + arm64
- Image tag:
on-pr-{{revision}} - Expires after 5 days, max 3 kept
- Security scans: Clair, Roxctl, Snyk SAST, ClamAV, ShellCheck, Unicode, RPM signature
Push Pipeline (.tekton/integration-service-push.yaml)
- Regular build (no coverage) + extra
build-instrumented-imagetask (with coverage) - Image tag:
{{revision}} - Same security scans as PR
Dockerfile Gotchas
- Builds two binaries:
manager(controller) andsnapshotgc(garbage collector) - Both ship in the same image, entrypoint is
/manager ENABLE_COVERAGEbuild arg switches between instrumented and production builds- Base image: UBI9 minimal, runs as user 65532 (non-root)
Webhook Validation Gotchas
| Rule | What happens if violated | |
|---|---|---|
| ITS name must be DNS-1035 | Webhook rejects with validation error (lowercase alphanumeric + hyphen, <63 chars) | |
SNAPSHOT param in ITS | Cannot be set manually — auto-injected by the service. Webhook rejects. | |
Git resolver: url vs repo+org | Must use one or the other, not both. Webhook rejects conflicting params. | |
| Snapshot validator | Has failurePolicy: Fail — invalid Snapshots are rejected, and Snapshot operations are blocked if the validating webhook is unavailable |
Coverage
- Tool: codecov, flag:
unit-tests - Patch target: 85% for changed coverable lines
- Ignores:
**/zz_generated*,e2e-tests/**, vendor - Patch coverage: informational only (non-blocking)
Common Mistakes
| Problem | Root cause | |
|---|---|---|
| CI fails with "uncommitted changes" | Didn't run make fmt, make generate manifests, or go mod tidy | |
| Build fails on missing deps | Didn't run go mod vendor after dependency change | |
| RBAC check fails | Used wildcard * in kubebuilder RBAC marker | |
| Coverage dropped | New code paths not covered by tests (check cover.out) | |
| Webhook rejects valid-looking ITS | Name contains uppercase, underscore, or is >63 chars | |
Missing list/watch verbs on cached-client RBAC marker | Informer reflector cannot populate cache without list and watch verbs |