name: konflux-onboarding
description: "Guides Konflux CI/CD pipeline onboarding for new components — upstream ODH Dockerfiles & Tekton pipelines, downstream RHOAI Dockerfile generation, DevOps skill integration, manifest overlays, and Jira tracking."
argument-hint: " [--skip-odh] [--skip-downstream] [--skip-jira]"
Konflux Onboarding
Onboard a component to Konflux CI/CD pipelines for both ODH (upstream) and RHOAI (downstream). This skill handles Dockerfiles, Tekton PipelineRun YAML, DevOps coordination, manifest overlays, and Jira updates.
Companion to /module-onboarding which handles Dashboard-side package scaffolding. This skill covers the CI/CD pipeline side.
Flags
Parse from $ARGUMENTS:
--skip-odh— skip Phases 1-2 (ODH upstream Dockerfile and Tekton pipelines)--skip-downstream— skip Phases 3-4 (RHOAI DevOps request and downstream Dockerfile)--skip-jira— skip Phase 7 (Jira updates)
Phase 0: Parse and Classify
Goal: Determine component type and detect existing state.
Extract the component name from
$ARGUMENTS(first positional argument). If missing, ask the user.Classify the component:
- Type A — Modular-arch package:
packages/<name>/exists. These are Node.js + optional Go BFF packages that useDockerfile.workspaceand deploy as Module Federation remotes. - Type B — Standalone Go component:
<name>/exists at repo root with ago.mod. These are Go services/operators with their own Dockerfile.
Validate the component name first, then use quoted path checks:
# Validate component name (lowercase alphanumeric + hyphens only) if ! echo "$COMPONENT_NAME" | grep -qE '^[a-z0-9]+(-[a-z0-9]+)*$'; then echo "Invalid component name"; exit 1 fi if [ -d "packages/${COMPONENT_NAME}" ]; then TYPE="A" elif [ -d "${COMPONENT_NAME}" ] && [ -f "${COMPONENT_NAME}/go.mod" ]; then TYPE="B" else # Ask user to clarify fi- Type A — Modular-arch package:
Detect existing state:
# Check for existing ODH Dockerfile # Type A: [ -f "packages/${COMPONENT_NAME}/Dockerfile.workspace" ] && echo "exists" # Type B: [ -f "${COMPONENT_NAME}/Dockerfile" ] && echo "exists" # Check for existing Tekton pipelines find .tekton -maxdepth 1 -name "*${COMPONENT_NAME}*push*.yaml" -print -quit 2>/dev/null find .tekton -maxdepth 1 -name "*${COMPONENT_NAME}*pull-request*.yaml" -print -quit 2>/dev/nullReport classification and state to user:
Component: <name> Type: A (modular-arch package) / B (standalone Go component) ODH Dockerfile: ✅ exists / ❌ missing Tekton push pipeline: ✅ exists / ❌ missing Tekton PR pipeline: ✅ exists / ❌ missing
Phase 1: ODH Upstream Dockerfile
Goal: Ensure the component has an upstream Dockerfile for ODH Konflux builds.
Skip if: --skip-odh flag, or Dockerfile already exists.
Type A
Check for packages/<name>/Dockerfile.workspace. If missing, scaffold from packages/plugin-template/Dockerfile.workspace.
Read the template from packages/plugin-template/Dockerfile.workspace and adapt:
- Set
ARG MODULE_NAME=<name> - Update
UI_SOURCE_CODEandBFF_SOURCE_CODEpaths - If the package has no BFF (no
packages/<name>/bff/directory), remove the BFF build stage and adjust the final stage to only copy UI artifacts - Check
packages/<name>/bff/go.modfor the Go version if BFF exists
See references/dockerfile-templates.md § Type A for the full template.
Type B
Check for <name>/Dockerfile. If missing, scaffold using the Type B template.
Read <name>/go.mod to determine Go version. Identify the binary build target from <name>/cmd/*/main.go.
See references/dockerfile-templates.md § Type B for the full template.
Verify: The Dockerfile builds from repo root context (not from the component subdirectory).
Phase 2: ODH Upstream Tekton Pipelines
Goal: Ensure .tekton/ has push and pull-request pipelines for this component.
Skip if: --skip-odh flag, or both pipeline files already exist.
Type A
Scaffold odh-mod-arch-<name>-push.yaml and odh-mod-arch-<name>-pull-request.yaml.
Use an existing Type A pipeline as reference (e.g., .tekton/odh-mod-arch-gen-ai-push.yaml). Apply substitutions from references/pipeline-templates.md:
COMPONENT_CI_NAME:odh-mod-arch-<name>-ciPIPELINE_NAME_PREFIX:odh-mod-arch-<name>QUAY_IMAGE:quay.io/opendatahub/odh-mod-arch-<name>DOCKERFILE_PATH:packages/<name>/Dockerfile.workspacePATH_CHANGED_EXPR:packages/<name>/**EXTRA_PATH_EXPR:|| "Dockerfile.workspace".pathChanged()SERVICE_ACCOUNT:build-pipeline-<name>(must be provisioned by DevOps)
Type B
Scaffold <name>-push.yaml and <name>-pull-request.yaml.
Use .tekton/dashboard-operator-push.yaml as reference. Apply substitutions:
COMPONENT_CI_NAME:<name>-ciPIPELINE_NAME_PREFIX:<name>QUAY_IMAGE:quay.io/opendatahub/<name>DOCKERFILE_PATH:<name>/DockerfilePATH_CHANGED_EXPR:<name>/**EXTRA_PATH_EXPR:|| "manifests/**".pathChanged()(if applicable)SERVICE_ACCOUNT:build-pipeline-<name>
Important: The service account must be provisioned by DevOps before the pipeline can run. Remind the user that Phase 3 (DevOps onboarding) handles this.
Phase 3: DevOps Onboarding Request
Goal: Generate component_onboarding_details.yaml files, validate them, and attach to a Jira ticket for DevOps automation.
Skip if: --skip-downstream flag.
Read references/devops-integration.md for the full integration guide.
Important: Two separate onboarding YAMLs are required — one for ODH and one for RHOAI. Each has different schema requirements. Run this phase twice.
Prerequisites
The DevOps skill (/create-component-onboarding-jira) is a Claude Code plugin from opendatahub-io/aiops-infra. It requires JIRA_USER_EMAIL and JIRA_API_TOKEN env vars for its Python scripts.
If those env vars are not set, you can do the equivalent work manually:
- Generate the YAML using the
generate_onboarding_yaml.pyscript - Validate using
validate_yaml_schema.py - Attach to Jira using the mcp-atlassian MCP tools
Scripts live at: ~/.claude/plugins/cache/opendatahub-skills/aiops-skills/0.1.0/
Step 3a: Collect Information (ODH run)
Ask the user for these values (with defaults where possible):
| Field | Q&A Question | Validation | Default |
|---|---|---|---|
product_context |
Which product? | ODH or RHOAI |
— |
build_type |
CI or Release build? (ODH only) | CI or Release |
— |
component_name |
Component name? | Must match ^odh-[a-z0-9]+(-[a-z0-9]+)*$ |
odh-<name> |
repo_url |
GitHub repo URL? | Must match ^https://github\.com/.+/.+$, must return HTTP 200 |
https://github.com/opendatahub-io/odh-dashboard |
repo_branch |
Branch to build? (ODH only) | Non-empty | main |
context_path |
Docker build context path? | Non-empty | ./ |
dockerfile_path |
Dockerfile path relative to context? | Non-empty | Type A: packages/<name>/Dockerfile.workspace, Type B: <name>/Dockerfile |
is_operator |
Is this an operator/controller? | true or false |
— |
operator_manifest_src_path |
Manifest source path? (if operator) | Non-empty | — |
operator_manifest_dest_path |
Manifest dest path? (if operator) | Non-empty | odh-<name> |
Step 3b: Collect Information (RHOAI run)
RHOAI requires additional fields beyond ODH:
| Field | Q&A Question | Validation | Notes |
|---|---|---|---|
target_rhoai_version |
Target RHOAI version? | Regex: ^\d+\.\d+(?:\.0)?(?:-ea[-.]?\d+)?$ |
Canonical form: X.Y or X.Y-ea-N |
architectures |
CPU architectures? | Subset of [x86_64, arm64, ppc64le, s390x] |
Default: [x86_64, arm64] |
release_category |
Release category? | Generally Available, Tech Preview, or Beta |
— |
long_description |
Component description (1-2 sentences)? | Non-empty | Auto-suggest from repo README |
short_description |
Short description (noun phrase)? | Non-empty | Auto-suggest from long_description |
repo_url |
GitHub repo URL? | — | https://github.com/red-hat-data-services/odh-dashboard |
repo_branch |
Auto-derived from version | — | rhoai-X.Y or rhoai-X.Y-ea.N |
dockerfile_path |
Dockerfile path? | Basename must start with Dockerfile.konflux |
Dockerfile.konflux.<name> |
Branch derivation (do NOT ask user):
- No EA suffix (e.g.,
3.5):repo_branch = rhoai-3.5 - EA suffix (e.g.,
3.5-ea-2):repo_branch = rhoai-3.5-ea.2
Step 3c: Generate and Validate YAML
For each product context (ODH, then RHOAI):
cd ~/.claude/plugins/cache/opendatahub-skills/aiops-skills/0.1.0
WORKDIR=$(mktemp -d)
YAML_PATH="${WORKDIR}/component_onboarding_details.yaml"
# Generate
uv run --script scripts/generate_onboarding_yaml.py \
--output "$YAML_PATH" \
--product-context "<ODH|RHOAI>" \
--component-name "<name>" \
--repo-url "<url>" \
--repo-branch "<branch>" \
--context-path "<path>" \
--dockerfile-path "<path>" \
[--build-type "<CI|Release>"] # ODH only
[--target-rhoai-version "<version>"] # RHOAI only
[--architectures "<arch1,arch2,...>"] # RHOAI only
[--release-category "<category>"] # RHOAI only
[--long-description "<desc>"] # RHOAI only
[--short-description "<desc>"] # RHOAI only
[--is-operator] # if operator
[--operator-manifest-src-path "<path>"] # if operator
[--operator-manifest-dest-path "<path>"] # if operator
# Validate against schema
uv run --script scripts/validate_yaml_schema.py \
"$YAML_PATH" \
schemas/component_onboarding_details.schema.json
Step 3d: Dockerfile Digest Check (RHOAI only)
Skip for ODH. For RHOAI, verify all FROM instructions use @sha256: digests:
uv run --script scripts/check_dockerfile_digests.py \
--dockerfile-url "<raw-github-url>"
If the downstream branch doesn't exist yet (HTTP 404), verify digests locally against the Dockerfile content from Phase 4 or an existing PR.
Step 3e: Attach to Jira
Ask user for the Jira issue key and parent feature ID.
Using mcp-atlassian MCP tools (if JIRA_USER_EMAIL/JIRA_API_TOKEN not set):
jira_update_issue— attach the YAML file and addyaml-attachedlabeljira_create_issue_link— link to parent feature with "Related" link typejira_add_comment— post a summary comment with component details
Name files distinctly: component_onboarding_details.yaml (ODH) and component_onboarding_details_rhoai.yaml (RHOAI).
Step 3f: Post-Attachment Flow
After attaching:
- DevOps GitLab CI picks up YAML attachments every ~2 hours
- Automated PRs are raised for Konflux component registration, release pipelines, Quay repos
- PRs require human review and merge
- This phase covers: Quay repo creation, Konflux component registration, release pipeline config, Renovate/automerge setup
Phase 4: RHOAI Downstream Dockerfile
Goal: Generate a downstream Dockerfile for the RHOAI build.
Skip if: --skip-downstream flag.
Generate Dockerfile.konflux.<name> content for the red-hat-data-services/odh-dashboard repo root.
Type A
Based on the upstream Dockerfile.workspace, generate a downstream variant with:
- SHA-pinned base images (use
skopeo inspectto get current digests, or use placeholder@sha256:<digest>) - Red Hat labels on the final stage
- Same FIPS flags as upstream (already uses
CGO_ENABLED=1 -tags strictfipsruntime)
See references/dockerfile-templates.md § Downstream Type A.
Type B
Generate from the upstream Dockerfile with these changes:
Builder:
registry.redhat.io/ubi9/go-toolset:<version>@sha256:<digest>(not Docker Hubgolang:)Add
USER rootafter FROM in builder stage (go-toolset runs non-root by default)Build flags:
CGO_ENABLED=1 GOOS=linux go build -a -ldflags="-s -w" -tags strictfipsruntimeRuntime:
registry.access.redhat.com/ubi9/ubi-minimal@sha256:<digest>(SHA-pinned)Red Hat labels on final stage:
LABEL com.redhat.component="odh-<name>-container" \ name="managed-open-data-hub/odh-<name>-rhel9" \ summary="ODH <Display Name>" \ description="<Description> for Red Hat OpenShift AI" \ io.k8s.display-name="ODH <Display Name>" \ io.k8s.description="<Description> for Red Hat OpenShift AI" \ io.openshift.tags="rhods,rhoai,odh,<name>"
See references/dockerfile-templates.md § Downstream Type B.
Pushing to the Downstream Repo
The downstream Dockerfile must be committed to the downstream repo (e.g. red-hat-data-services/odh-dashboard), not to the upstream repo (opendatahub-io/odh-dashboard).
Identify the downstream remote. Scan
git remote -vfor the downstream repo URL (e.g.red-hat-data-services/odh-dashboard). The remote name varies by checkout — it may beorigin,downstream, or something else.DOWNSTREAM_REMOTE=$(git remote -v | grep 'red-hat-data-services/odh-dashboard' | head -1 | awk '{print $1}') if [ -z "$DOWNSTREAM_REMOTE" ]; then echo "ERROR: No remote found for red-hat-data-services/odh-dashboard" echo "Add it with: git remote add downstream git@github.com:red-hat-data-services/odh-dashboard.git" exit 1 fi echo "Downstream remote: $DOWNSTREAM_REMOTE"Determine the target branch. Use the
repo_branchvalue from Phase 3 (e.g.rhoai-3.5-ea.2). Fetch and verify it exists:git fetch "$DOWNSTREAM_REMOTE" "$TARGET_BRANCH"Create a feature branch, add the Dockerfile, and push:
# Create branch from the downstream target git checkout -b "<jira-key>-dockerfile-konflux" "$DOWNSTREAM_REMOTE/$TARGET_BRANCH" # Write Dockerfile.konflux.<name> at repo root # (use the content generated above) git add "Dockerfile.konflux.<name>" git commit -m "<JIRA-KEY>: Add Dockerfile.konflux.<name> for RHOAI Konflux builds" git push "$DOWNSTREAM_REMOTE" "<jira-key>-dockerfile-konflux"Create a PR against the downstream repo targeting
$TARGET_BRANCH:gh pr create \ --repo red-hat-data-services/odh-dashboard \ --base "$TARGET_BRANCH" \ --head "<jira-key>-dockerfile-konflux" \ --title "<JIRA-KEY>: Add Dockerfile.konflux.<name>" \ --body "Adds the downstream Konflux Dockerfile for the <name> component. This Dockerfile uses SHA-pinned base images and FIPS-compliant build flags as required for RHOAI builds."
Do NOT write the Dockerfile to the upstream repo or create a PR against opendatahub-io/odh-dashboard — the downstream Dockerfile only exists in the downstream repo.
Phase 5: Manifest Overlay (Type A only)
Goal: Scaffold deployment manifests for a modular-arch package.
Skip if: Type B, or manifests already exist in manifests/modular-architecture/modules/<name>/.
For Type A packages, check if manifests/modular-architecture/modules/<name>/ exists. If not, scaffold:
- Deployment overlay adding the module container
- Service port configuration
- Image parameter for Konflux/operator injection
- Kustomization.yaml entry
Reference existing module overlays in manifests/modular-architecture/modules/ for the pattern.
Phase 6: OpenShift CI (instructions only)
Goal: Provide instructions for openshift/release repo configuration.
This cannot be automated — it requires changes in a separate repository (openshift/release).
Prerequisite: The component's Quay repository must have the opendatahub+openshift_ci robot account with push permission. Request this via #rhoai-devtestops-request Slack channel if not already configured.
Provide the user with:
- The config snippet needed for
ci-operator/config/opendatahub-io/odh-dashboard/ - Reference to existing PRs for similar components
- The PR process for
openshift/release
To add OpenShift CI for this component:
1. Ensure Quay repo has opendatahub+openshift_ci robot account with push permission
2. Create a config file in openshift/release:
ci-operator/config/opendatahub-io/odh-dashboard/<name>.yaml
3. Reference existing configs in the same directory for the pattern
4. Submit a PR to openshift/release
Phase 7: Jira Updates
Goal: Update tracking Jira issues with onboarding progress.
Skip if: --skip-jira flag.
If a Jira issue key was provided or is known from context, add a comment documenting:
- What was completed (files created, phases executed)
- What remains (pending DevOps automation, manual steps)
- Links to any PRs created
Phase 8: Verification Report
Goal: Summary of all work done and remaining steps.
Print a final report:
## Konflux Onboarding Report: <name>
### Component Classification
- Type: A/B
- Component: <name>
### Completed
- [ ] ODH Dockerfile: <path> (created/already existed/skipped)
- [ ] Tekton push pipeline: <path> (created/already existed/skipped)
- [ ] Tekton PR pipeline: <path> (created/already existed/skipped)
- [ ] DevOps onboarding: requested/skipped
- [ ] RHOAI Dockerfile: content generated/skipped
- [ ] Manifest overlay: created/already existed/skipped/N/A
- [ ] OpenShift CI: instructions provided/skipped
- [ ] Jira updated: yes/skipped
### Files Created/Modified
- <list of files>
### Remaining Manual Steps
1. Review and merge Tekton pipeline PRs
2. Wait for DevOps GitLab CI to process onboarding request (~2-4 hours)
3. Review and merge DevOps-generated PRs (check Jira labels for progression)
4. Review and merge Dockerfile.konflux.<name> PR in the downstream repo
5. Submit OpenShift CI config PR to openshift/release
6. Coordinate operator integration with Platform team (RHOAIENG-37067) — update operator component references, OLM bundle, and test integration
7. Verify first build succeeds end-to-end (both ODH and RHOAI)