| name | konflux-onboarding |
| description | Guides Konflux CI/CD pipeline onboarding for new components — Jira tracking epic, upstream ODH Dockerfile, downstream RHOAI Dockerfile, standalone deployment manifests, OpenShift CI, dashboard-operator registration, and DevOps coordination. Operator registration is deferred here (not in /module-onboarding) because the operator deploys the module image, which must be buildable first. |
| argument-hint | <component-name> [--jira <EPIC-KEY>] [--skip-jira] [--skip-odh] [--skip-downstream] [--skip-openshift-ci] |
Konflux Onboarding
Onboard a component to Konflux CI/CD pipelines for both ODH (upstream) and RHOAI (downstream). This skill handles Jira tracking, Dockerfiles, standalone manifests, OpenShift CI, dashboard-operator registration, and DevOps coordination.
Companion to /module-onboarding which handles Dashboard-side package scaffolding. This skill covers the CI/CD pipeline side plus operator registration (deferred here because the operator deploys the module image, which must be buildable first).
Note: Tekton PipelineRun YAML files are not created by this skill — they are generated by the DevOps automation after the onboarding requests are processed (see Phase 6).
Flags
Parse from $ARGUMENTS:
--jira <EPIC-KEY> — use an existing Jira epic instead of cloning the RHOAIENG-37060 template
--skip-jira — skip all Jira operations (Phase 1 clone + Phase 7 updates)
--skip-odh — skip Phase 2 (ODH upstream Dockerfile)
--skip-downstream — skip Phase 3 (RHOAI downstream Dockerfile)
--skip-openshift-ci — skip Phase 5 (OpenShift CI configuration in openshift/release)
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 use Dockerfile.workspace and deploy as standalone pods (independent Kubernetes Deployments) running Module Federation remotes.
- Type B — Standalone Go component:
<name>/ exists at repo root with a go.mod. These are Go services/operators with their own Dockerfile.
Validate the component name first, then use quoted path checks:
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
fi
-
Detect existing state:
[ -f "packages/${COMPONENT_NAME}/Dockerfile.workspace" ] && echo "exists"
[ -f "/Dockerfile" ] &&
Phase 1: Clone Tracking Epic
Goal: Create a Jira epic to track the full onboarding workflow by cloning the RHOAIENG-37060 template epic and all its subtasks.
Skip if: --skip-jira flag is set.
If --jira <EPIC-KEY> was provided, use that existing epic and skip to Phase 2.
Step 1a: Create the Parent Epic
Create a new epic with the component name in the title:
project_key="RHOAIENG",
issue_type="Epic",
summary="Konflux Onboarding: <name>",
description="Konflux CI/CD onboarding tracking epic for the <name> component.\n\nCloned from template: [RHOAIENG-37060|https://issues.redhat.com/browse/RHOAIENG-37060]",
components="AI Core Dashboard",
additional_fields={
"customfield_10001": "ec74d716-af36-4b3c-950f-f79213d08f71-1809",
"priority": {"name": "Major"},
"labels": ["dashboard-monarch-scrum"]
}
Step 1b: Create All 8 Subtasks
Create the following subtasks under the new epic.
Critical API notes:
parent must be a plain string (e.g., "RHOAIENG-XXXXX"), NOT an object like {"key": "..."} — the API will reject the object form.
- Do NOT set
customfield_10001 (team) on subtasks — they inherit team from the parent epic automatically. Setting it causes an API error.
| # | Summary | Priority | Description |
|---|
| 1 | <name>: Onboard module to Dashboard Repo | Major | Module scaffolding in the monorepo. Fully automated by /module-onboarding skill. |
| 2 | <name>: Create Konflux Onboarding Jira Tickets | Major | DevOps Konflux component registration tickets. Automated by DevOps /create-component-onboarding-jira skill. |
| 3 | <name>: Create Dockerfiles & Tekton Pipelines | Major | Create upstream ODH Dockerfile, downstream RHOAI Dockerfile, and Tekton pipelines. Partially automated by /konflux-onboarding skill (Dockerfiles only — Tekton pipelines are generated by DevOps automation). |
| 4 | <name>: Track & Verify ODH Konflux Onboarding | Major | Track ODH Konflux component onboarding (Quay repo, build pipeline, release config). Automated by DevOps CI. |
| 5 | <name>: Set up module for OpenShift CI builds | Major | Configure OpenShift CI in openshift/release repo (ci-operator config + prowgen jobs). Partially automated by /konflux-onboarding Phase 5. |
| 6 | <name>: Create Standalone Module Manifests | Major | Create standalone deployment manifests in manifests/modules/<name>/. Partially automated by /konflux-onboarding Phase 4 (Type A only). |
| 7 | <name>: Onboard Module in Operator | Major | Register the module in dashboard-operator/internal/controller/modules.go with all fields and update test assertions in modules_test.go and charts/dashboard/values.yaml. Proxy paths and imagesMap entries are read from the registry (single source of truth). The opendatahub-operator also needs a one-line addition to relatedImages() in internal/controller/modules/dashboard/support.go — open a PR and request review in #ai-core-platform-requests Slack channel. |
| 8 | <name>: Track & Verify RHOAI Konflux Onboarding |
For each subtask:
project_key="RHOAIENG",
issue_type="Sub-task",
summary="<name>: <title from table>",
description="<description from table adapted with component name and relevant links>",
components="AI Core Dashboard",
additional_fields={
"parent": "<EPIC-KEY>",
"priority": {"name": "Major"},
"labels": ["dashboard-monarch-scrum"]
}
Step 1c: Link to Template Epic
Add a "Cloners" link between the new epic and the template:
jira_create_issue_link(
link_type="Cloners",
inward_issue_key="<NEW-EPIC-KEY>",
outward_issue_key="RHOAIENG-37060"
)
Step 1d: Report
Print the epic key and all subtask keys to the user. These will be updated as subsequent phases complete.
Fallback: Manual Clone
If Jira API access is not available (missing credentials, MCP not configured, or connection errors), ask the user to:
- Open RHOAIENG-37060 in Jira
- Clone the epic manually (Actions → Clone)
- Rename the cloned epic to "Konflux Onboarding:
<name>"
- Provide the new epic key via
--jira <EPIC-KEY> and re-run the skill
This avoids token-heavy retry loops when MCP is misconfigured.
Phase 2: 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_CODE and BFF_SOURCE_CODE paths
- 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.mod for 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 3: RHOAI Downstream Dockerfile
Goal: Generate a downstream Dockerfile for the RHOAI build.
Skip if: --skip-downstream flag.
Important: This phase must complete before Phase 6 (DevOps Onboarding) because the DevOps RHOAI onboarding YAML references Dockerfile.konflux.<name> as the dockerfile_path — it must exist in the downstream repo.
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 inspect to 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 Hub golang:)
-
Add USER root after 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 strictfipsruntime
-
Runtime: 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 -v for the downstream repo URL (e.g. red-hat-data-services/odh-dashboard). The remote name varies by checkout — it may be origin, 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. Ask the user for the target RHOAI version and derive the branch:
- 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
Fetch and verify it exists:
git fetch "$DOWNSTREAM_REMOTE" "$TARGET_BRANCH"
-
Create a feature branch, add the Dockerfile, and push:
git checkout -b "<jira-key>-dockerfile-konflux" "$DOWNSTREAM_REMOTE/$TARGET_BRANCH"
git add "Dockerfile.konflux.<name>"
git commit -m
git push
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 4: Standalone Module Manifests (Type A only)
Goal: Scaffold standalone deployment manifests for a modular-arch package. Standalone mode is the primary deployment topology — each module gets its own Kubernetes Deployment managed by the dashboard-operator.
Skip if: Type B, or manifests already exist in manifests/modules/<name>/.
Note: /module-onboarding does not create standalone manifests or operator registration — those are handled here. If manifests already exist (e.g., from a previous run), this phase will detect them and skip.
For Type A packages, check if manifests/modules/<name>/ exists. If not, scaffold the following files:
deployment.yaml — Independent Deployment with 2 replicas, TLS config, and a dedicated ServiceAccount
service.yaml — Service exposing the module's BFF port (name pattern: odh-dashboard-<slug>-ui)
networkpolicy.yaml — NetworkPolicy for inter-BFF egress (to the odh-dashboard pod for core-bff communication)
service-account.yaml — Dedicated ServiceAccount for SA isolation
cluster-role.yaml + cluster-role-binding.yaml — Module-specific RBAC
kustomization.yaml — Kustomize entry referencing all resources
params.env — Kustomize parameter defaults (image reference)
Reference existing modules in manifests/modules/ (e.g., gen-ai/, model-registry/) for the exact patterns and field values.
Phase 5: OpenShift CI
Goal: Configure OpenShift CI for the component in the openshift/release repository.
Skip if: --skip-openshift-ci flag.
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.
Step 5a: Prepare the Repository
Ask the user for their fork of openshift/release (e.g., git@github.com:<user>/release.git). Clone it and create a feature branch:
WORK_DIR=$(mktemp -d)
git clone --depth 1 <fork-url> "$WORK_DIR/openshift-release"
cd "$WORK_DIR/openshift-release"
git remote add upstream https://github.com/openshift/release.git
git fetch upstream main
git checkout -b <component-name>-openshift-ci upstream/main
Step 5b: Modify the Configuration File
Edit only the following file:
ci-operator/config/opendatahub-io/odh-dashboard/opendatahub-io-odh-dashboard-main.yaml
Read the existing file and add entries for the new component following the existing patterns. Three entries are needed:
-
Image build — add to images.items[]:
For Type A:
- context_dir: .
dockerfile_path: ./packages/<name>/Dockerfile.workspace
to: odh-mod-arch-<name>-image
For Type B:
- context_dir: .
dockerfile_path: ./<name>/Dockerfile
to: odh-<name>-image
-
PR image mirror test — add to tests[]:
- as: odh-<image-name>-pr-image-mirror
steps:
dependencies:
SOURCE_IMAGE_REF: odh-<image-name>-image
env:
IMAGE_REPO: odh-<image-name>
workflow: opendatahub-io-ci-image-mirror
-
Postsubmit image mirror test — add to tests[]:
- as: odh-<image-name>-image-mirror
postsubmit: true
steps:
dependencies:
SOURCE_IMAGE_REF: odh-<image-name>-image
env:
IMAGE_REPO: odh-<image-name>
RELEASE_VERSION: main
workflow:
For Type A, <image-name> is mod-arch-<name>. For Type B, <image-name> is dashboard-<name> (or just the component name if it already has a clear prefix like dashboard-operator).
Match the naming pattern of existing entries in the file.
YAML Formatting Requirements
The opendatahub-io-odh-dashboard-main.yaml file is consumed by CI automation and must remain valid, well-formatted YAML. When editing:
- Preserve existing indentation — the file uses 2-space indentation consistently. Match the exact indentation of surrounding entries.
- Preserve key ordering — add new entries at the end of each list (
images.items[], tests[]) to minimize diff noise and merge conflicts.
- Validate after editing — run
python3 -c "import yaml; yaml.safe_load(open('<file>'))" or yq '.' <file> > /dev/null to verify the file is still valid YAML before committing.
- No trailing whitespace — ensure lines don't have trailing spaces.
- Consistent quoting — follow the existing style (unquoted strings where possible, single quotes for values that need them).
- Watch for indentation errors in multi-line values — the
cel-expression annotations span multiple lines. Match the exact indentation of similar existing entries.
Step 5c: Generate Job Files
Run prowgen to generate the job configuration files. This requires Docker or Podman:
cd "$WORK_DIR/openshift-release"
if command -v docker &>/dev/null && docker info &>/dev/null; then
CONTAINER_ENGINE=docker make ci-operator-prowgen
elif command -v podman &>/dev/null && podman info &>/dev/null; then
CONTAINER_ENGINE=podman make ci-operator-prowgen
else
echo "ERROR: Neither Docker nor Podman is available."
echo "The user must run 'CONTAINER_ENGINE=docker make ci-operator-prowgen' manually."
fi
This generates/updates files under ci-operator/jobs/opendatahub-io/odh-dashboard/. These generated files must be included in the PR.
If neither container engine is available, note in the PR description that CONTAINER_ENGINE=docker make ci-operator-prowgen must be run and the generated files added before merge.
Step 5d: Commit, Push, and Create PR
cd "$WORK_DIR/openshift-release"
git add ci-operator/config/opendatahub-io/odh-dashboard/ ci-operator/jobs/opendatahub-io/odh-dashboard/
git commit -m "Add <component-name> to OpenShift CI builds and Quay image mirroring"
git push origin <component-name>-openshift-ci
Create a PR against openshift/release targeting the main branch:
gh pr create \
--repo openshift/release \
--base main \
--head <user>:<component-name>-openshift-ci \
--title "Add <component-name> to odh-dashboard OpenShift CI" \
--body "Adds CI configuration for the <component-name> component of odh-dashboard.
Changes:
- Image build entry for <component-name> Dockerfile
- PR image mirror test for pre-merge Quay pushes
- Postsubmit image mirror test for post-merge Quay pushes
- Prowgen-generated job files
Reference: https://github.com/openshift/release/pull/73525"
Step 5e: Cleanup
rm -rf "$WORK_DIR"
Remind the user to verify opendatahub+openshift_ci robot account has push on the Quay repo if not already confirmed.
Phase 5a: Dashboard-Operator Registration (Type A only)
Goal: Register the module in the dashboard-operator so it can manage the module's lifecycle. This step is intentionally placed after OpenShift CI setup because the operator deploys the module image — if registered before the image is buildable, the pod enters ImagePullBackOff.
Skip if: Type B, or module is already registered in dashboard-operator/internal/controller/modules.go.
Prerequisite: The OpenShift CI PR (Phase 5) should be merged and the first image build should be available on Quay before this registration is deployed. The registration can be committed in the same PR as the module scaffolding, but must not be merged until the CI pipeline is producing images.
Step 1: Ask DSC and dependency questions
-
Ask the user: Which DSC component(s) gate this module? (e.g., modelregistry, aipipelines, trustyai, mlflowoperator). These determine when the operator enables/disables the module based on DataScienceCluster availability. Default: none (module is always enabled).
-
Ask the user: Does this module depend on any other modules? (e.g., genAi). If a dependency is disabled, this module will also be disabled. Default: none.
Step 2: Module registry — dashboard-operator/internal/controller/modules.go
Read the file and find the moduleRegistry map. Add a new entry with all required fields:
"<camelCase>": {
Name: "<camelCase>",
ContainerName: "<name>-ui",
Port: <production-service-port>,
ImageEnvVar: "RELATED_IMAGE_ODH_MOD_ARCH_<UPPER_SNAKE>_IMAGE",
ManifestSlug: "<name>",
RequiredDSCComponents: []string{<dsc-components>},
InterModuleDependencies: []string{<dependencies>},
},
The production service port is in packages/<name>/package.json at module-federation.service.port. If RequiredDSCComponents or InterModuleDependencies are empty, omit them entirely.
Optional fields (only needed for non-standard modules):
ProxyPaths: set if the module uses a non-standard proxy path (not /<ManifestSlug>/api → /api)
InterBFFDeps: set if this module's BFF needs to call another module's BFF service
No changes needed to module_deploy.go (proxy paths read from ModuleDefinition) or support.go (image map auto-generated from registry).
Step 3: Update tests — dashboard-operator/internal/controller/modules_test.go
Read the file and update:
TestModuleRegistry — increment the assert.Len count by 1 (e.g., from 8 to 9)
TestModuleNames — add "<camelCase>" to the expected sorted name list in the correct alphabetical position
TestResolveModuleStatuses — update wantLen values: increment the standard case by 1 and the unknown-module case by 1
Step 4: Helm chart related images — dashboard-operator/charts/dashboard/values.yaml
Read the file and find the relatedImages: section. Add an entry for the new module's image env var:
RELATED_IMAGE_ODH_MOD_ARCH_<UPPER_SNAKE>_IMAGE: ""
Place it alphabetically among the existing RELATED_IMAGE_ODH_MOD_ARCH_* entries.
Step 5: Verify operator changes
cd dashboard-operator && go build ./... && go test ./internal/controller/... -count=1
This confirms the registry entry compiles, derived fields are correct, and test assertions match the updated module count.
Phase 6: DevOps Onboarding
Goal: Prepare for DevOps Konflux component onboarding.
This phase does not run the DevOps skill inline — the user should run it separately after this skill completes, once the Dockerfiles exist. Tekton PipelineRun YAML files are created by the DevOps automation, not by this skill.
What to Do
-
Inform the user that the DevOps onboarding skill needs to be run twice (once for ODH, once for RHOAI):
Next step: Run the DevOps onboarding skill to create Konflux component registration tickets.
Two runs are required — one for ODH (upstream) and one for RHOAI (downstream):
1. Install the DevOps skill (if not already installed):
/plugin install aiops-skills@opendatahub-skills:0.1.0
2. Run for ODH:
/create-component-onboarding-jira
- Product: ODH
- Component name: odh-<name> (must start with "odh-")
- Repo URL: https://github.com/opendatahub-io/odh-dashboard
- Branch: main
- Dockerfile: <Type A: packages/<name>/Dockerfile.workspace, Type B: <name>/Dockerfile>
3. Run for RHOAI:
/create-component-onboarding-jira
- Product: RHOAI
- Component name: odh-<name>
- Repo URL: https://github.com/red-hat-data-services/odh-dashboard
- Branch: (auto-derived from RHOAI version)
- Dockerfile: Dockerfile.konflux.<name>
The DevOps automation will handle:
- Quay repository creation
- Konflux component registration
- Tekton PipelineRun YAML generation
- Release pipeline configuration
- Renovate / automerge setup
-
Collect key details the user will need for the DevOps skill runs and print them together for easy reference.
Read references/devops-integration.md for the full integration guide including Q&A flow, schema validation, and troubleshooting.
Phase 7: Jira Updates & Verification Report
Goal: Update tracking Jira subtasks and produce a final summary.
Skip Jira updates if: --skip-jira flag.
Jira Updates
If a tracking epic was created in Phase 1 (or provided via --jira), update each subtask with progress:
- Subtask 1 (Module onboarding): Link to module onboarding PR if applicable
- Subtask 3 (Dockerfiles & Tekton): Add comment noting which Dockerfiles were created, add PR links
- Subtask 5 (OpenShift CI): Link to the
openshift/release PR
- Subtask 6 (Standalone module manifests): Note whether manifests were created in
manifests/modules/<name>/ (Type A) or N/A (Type B)
- Subtask 7 (Operator): Link to the PR if operator registration was done in Phase 5a; note the opendatahub-operator change requires a separate PR reviewed via
#ai-core-platform-requests
For subtasks covered by DevOps automation (2, 4, 8), add a comment noting they will be tracked via the DevOps onboarding flow after the user runs /create-component-onboarding-jira.
Verification Report
Print a final report:
## Konflux Onboarding Report: <name>
### Component Classification
- Type: A/B
- Component: <name>
- Image name: <image-name>
### Tracking Epic
- Epic: <EPIC-KEY> (or "skipped")
- Subtask keys: <list>
### Completed
- [ ] Tracking epic cloned: <EPIC-KEY>/skipped
- [ ] ODH Dockerfile: <path> (created/already existed/skipped)
- [ ] RHOAI Dockerfile: content generated/skipped
- [ ] Standalone module manifests (`manifests/modules/<name>/`): created/already existed/skipped/N/A
- [ ] OpenShift CI: PR created/skipped
- [ ] Dashboard-operator registration: done/already registered/skipped/N/A
- [ ] Jira subtasks updated: yes/skipped
### Files Created/Modified
- <list of files>
### Next Steps (User Action Required)
1. Run DevOps onboarding skill for ODH: `/create-component-onboarding-jira` (see Phase 6 output for details)
2. Run DevOps onboarding skill for RHOAI: `/create-component-onboarding-jira` (see Phase 6 output for details)
3. Wait for DevOps GitLab CI to process onboarding requests (~2-4 hours each)
4. Review and merge DevOps-generated PRs (check Jira labels for progression)
5. Review and merge Dockerfile.konflux.<name> PR in the downstream repo
6. Review and merge OpenShift CI PR in openshift/release
7. Verify opendatahub+openshift_ci robot account has push on Quay repo
8. Open a PR against `opendatahub-io/opendatahub-operator` adding `RELATED_IMAGE_ODH_MOD_ARCH_<UPPER_SNAKE>_IMAGE` to `relatedImages()` in `internal/controller/modules/dashboard/support.go`, then request review in `#ai-core-platform-requests` Slack channel
9. Verify first build succeeds end-to-end (both ODH and RHOAI)