Skip to content

fix(deploy): register openshell gateway CLI and sync GitOps docs to hp-fleet-gitops#782

Merged
aredenba-rh merged 5 commits into
mainfrom
fix/ci-fleet-apps-deploy-tag
Jul 2, 2026
Merged

fix(deploy): register openshell gateway CLI and sync GitOps docs to hp-fleet-gitops#782
aredenba-rh merged 5 commits into
mainfrom
fix/ci-fleet-apps-deploy-tag

Conversation

@aredenba-rh

Copy link
Copy Markdown
Collaborator

Summary

  • HYPERFLEET-XXX

Test Plan

  • Unit tests added/updated
  • make test-all passes
  • make lint passes
  • Helm chart changes validated with make test-helm (if applicable)
  • Deployed to a development cluster and verified (if Helm/config changes)
  • E2E tests passed (if cross-component or major changes)

aredenba-rh and others added 3 commits July 1, 2026 17:30
…nerate

Previously, regenerating maintenance jobs raised an error if any changed
data source still needed an ingest prepare, forcing the operator to queue
maintenance jobs first just to refresh JobPackages. Now the pipeline runs
ingest_only syncs for those sources, waits for completion, and then builds
the maintenance jobs from the refreshed data in a single step.

Co-authored-by: Cursor <cursoragent@cursor.com>
The api-entrypoint-openshift.sh readiness loop polled `openshell status`
for "Connected", but nothing ever ran `openshell gateway add` to register
the gateway with the CLI's local config. The openshell-bootstrap init
container stages the mTLS certs but its image only ships the gateway
server binary, not the client CLI, so it can't register itself. The api
container (which has the CLI) now runs an idempotent `gateway add` using
the certs staged by the init container before waiting on status, fixing a
CrashLoopBackOff (exit 137) in kartograph-stage.

Also documents that stage/prod manifests are now sourced from GitLab
fleet-apps (what ArgoCD reads) with hp-fleet-gitops as the Konflux
deploy-tag PR target, and adds verification scripts to check the two
repos stay in sync and to validate the Vault-backed extraction-runtime
secret ESO reads for kartograph-stage.

Co-authored-by: Cursor <cursoragent@cursor.com>
hp-gitops-tenants PR #9 repointed the hp-fleet ApplicationSet from GitLab
fleet-apps to GitHub hp-fleet-gitops, so ArgoCD now reads the same repo
Konflux already opens deploy-tag PRs against. Update the reference
Application spec and README accordingly, and flip
verify-fleet-apps-kartograph.sh to validate hp-fleet-gitops as canonical
(fleet-apps drift is now informational only, and
networkpolicy-sticky-runtime.yaml being absent is expected, not missing).

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 876769e7-7128-4336-ab4d-29fdcfe7e50c

📥 Commits

Reviewing files that changed from the base of the PR and between 6948452 and 211c25e.

📒 Files selected for processing (2)
  • scripts/verify-fleet-apps-kartograph.sh
  • src/api/scripts/api-entrypoint-openshift.sh
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • openshift-hyperfleet/architecture (manual)
  • openshift-hyperfleet/hyperfleet-api (manual)
  • openshift-hyperfleet/hyperfleet-sentinel (manual)
  • openshift-hyperfleet/hyperfleet-adapter (manual)
  • openshift-hyperfleet/hyperfleet-broker (manual)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/api/scripts/api-entrypoint-openshift.sh
  • scripts/verify-fleet-apps-kartograph.sh

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Maintenance job regeneration now prepares changed/unprepared sources via ingest-only sync before rebuilding pending jobs.
    • OpenShift gateway bootstrap now supports configurable gateway name and URL (with defaults).
  • Bug Fixes
    • Improved maintenance-ingest failure detection and user-facing guidance in the graph maintenance UI.
    • Better Vault extraction runtime validation diagnostics (including clearer failure reasons) and more informative gateway bootstrap error reporting.
  • Documentation
    • Updated deployment documentation and ArgoCD stage configuration to use the current GitOps source, including PR-based image tag updates.
  • Tests
    • Updated unit coverage to verify the “prepare then regenerate” maintenance regeneration flow.

Walkthrough

Kartograph stage ArgoCD now targets hp-fleet-gitops, and the README documents PR-based newTag updates instead of direct pushes. Two new verification scripts check GitOps drift and Vault KV v2 secret shape for extraction runtime. Maintenance job regeneration now prepares unready sources with ingest-only syncs before rebuilding jobs, and the UI failure mapping was updated. The OpenShift entrypoint now resolves gateway name and URL from optional environment variables.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Service as MaintenancePipelineService
  participant SyncRunner
  participant JobRepo
  participant UI as GraphMaintenanceWorkspace
  Service->>SyncRunner: ingest_only sync for unprepared sources
  SyncRunner-->>Service: completion status
  Service->>JobRepo: regenerate pending maintenance jobs
  Service-->>UI: maintenance ingest failure text
Loading

CWE-829 (Untrusted control sphere): deploy/argocd/kartograph-stage.yaml repoints ArgoCD to hp-fleet-gitops; the new repoURL and project boundary must be explicitly authorized.

CWE-494 (Download of code without integrity check): scripts/verify-fleet-apps-kartograph.sh hard-resets both repos to origin/main; no signature or commit integrity check is present.

CWE-798 (Use of hard-coded credentials): scripts/verify-vault-extraction-runtime.py reads VAULT_TOKEN and sends it as X-Vault-Token; token handling must avoid logs and error echoing.

CWE-532 (Insertion of sensitive information into log file): the Vault verifier prints secret diagnostics; only key names, paths, and status text should appear, not secret values or decoded ADC content.

🚥 Pre-merge checks | ✅ 9 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
No Pii Or Sensitive Data In Logs ⚠️ Warning scripts/verify-vault-extraction-runtime.py logs raw Vault error bodies via {err or payload} on unexpected HTTP statuses, a CWE-532 exposure risk. Redact response bodies from logs; print only status/code and a short non-sensitive summary, with raw payloads behind an opt-in debug flag.
Description check ❓ Inconclusive The description is related but too generic to describe the actual changes beyond a placeholder ticket and checklist. Replace the placeholder summary with a concise description of the deploy, GitOps, and gateway-registration changes.
✅ Passed checks (9 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main change set: OpenShell gateway registration and GitOps docs/source migration to hp-fleet-gitops.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Sec-02: Secrets In Log Output ✅ Passed No changed non-test code logs/interpolates actual tokens, passwords, credentials, or secrets; only redacted or generic messages are printed. CWE-532 not triggered.
No Hardcoded Secrets ✅ Passed No CWE-798/CWE-321 hardcoded secrets found: changed files use env vars and secret names only; no embedded creds or long base64 literals.
No Weak Cryptography ✅ Passed No CWE-327/CWE-208 issues: changed files use no md5/des/rc4/ECB/SHA1-for-security and no secret/HMAC compare paths.
No Injection Vectors ✅ Passed No CWE-89/78/79/502 patterns found in changed code: no SQL concat, exec/eval, template.HTML, or yaml.Unmarshal; shell args stay quoted.
No Privileged Containers ✅ Passed No privileged true/hostNetwork/hostPID/hostIPC/SYS_ADMIN or root USER/runAsUser:0 found; Dockerfile uses USER 65532:65532. CWE-250 not present.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ci-fleet-apps-deploy-tag
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch fix/ci-fleet-apps-deploy-tag

Comment @coderabbitai help to get the list of available commands.

Comment thread scripts/verify-vault-extraction-runtime.py Fixed
Comment thread scripts/verify-vault-extraction-runtime.py Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/api/infrastructure/management/maintenance_pipeline_service.py (1)

205-214: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Add a per-source guard before launching ingest-only syncs

src/api/infrastructure/management/maintenance_pipeline_service.py:785-812 still creates a fresh DataSourceSyncRun for every source without checking for an existing pending/ingesting run or taking a lock. Concurrent trigger/regenerate calls can enqueue duplicate ingest-only runs for the same data source (CWE-362). Gate this with an active-run check or DB-backed lock so only one ingest can start per source.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/api/infrastructure/management/maintenance_pipeline_service.py` around
lines 205 - 214, The ingest-only launch path in MaintenancePipelineService can
create duplicate DataSourceSyncRun entries for the same source when
trigger/regenerate race. Update the per-source sync start flow in the relevant
helper that prepares ingest-only runs to first check for an existing active run
(pending or ingesting) or acquire a DB-backed lock before creating a new run.
Use the existing maintenance pipeline methods such as
_prepare_changed_sources_for_maintenance and the sync-run creation logic around
the ingest-only source loop to ensure only one ingest can start per data source
at a time.
🧹 Nitpick comments (3)
src/api/infrastructure/management/maintenance_pipeline_service.py (2)

208-214: 🩺 Stability & Availability | 🔵 Trivial | 🏗️ Heavy lift

Up to 300s synchronous poll inside regenerate_maintenance_jobs.

Calling _prepare_changed_sources_for_maintenance, which polls _wait_for_sync_runs with _MAINTENANCE_INGEST_WAIT_TIMEOUT_SECONDS = 300.0, blocks the caller for up to 5 minutes. If this is invoked from a synchronous HTTP request handler (e.g. POST .../regenerate-jobs), most reverse-proxy/gateway defaults (30–60s) will time out and retry before this returns, potentially triggering duplicate ingest launches per the race above.

Also applies to: 252-277

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/api/infrastructure/management/maintenance_pipeline_service.py` around
lines 208 - 214, `regenerate_maintenance_jobs` currently blocks on
`_prepare_changed_sources_for_maintenance`, which can wait up to 300s via
`_wait_for_sync_runs` and time out synchronous request handlers. Refactor the
`needs_ingest` path in
`regenerate_maintenance_jobs`/`_prepare_changed_sources_for_maintenance` to
avoid long in-request polling by moving the wait-and-launch flow to an async
background job or returning immediately after enqueuing the ingest, and keep
`find_by_knowledge_graph`/`_changed_sources` refresh logic aligned with the new
non-blocking flow.

252-277: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate ingest-wait/classify logic.

The timeout → ValueError, failedValueError, unexpected-state → ValueError sequence in _prepare_changed_sources_for_maintenance (Lines 266-276) is copy-pasted from _trigger_for_kg (Lines 364-386), just with different error surfaces (raise vs. _fail_latest_run). Extract a shared _classify_sync_statuses(statuses) -> None helper (raising) that both call sites wrap appropriately, to avoid the two drifting apart.

Also applies to: 363-386

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/api/infrastructure/management/maintenance_pipeline_service.py` around
lines 252 - 277, The timeout/failed/unexpected-state classification logic in
_prepare_changed_sources_for_maintenance is duplicated with _trigger_for_kg and
should be centralized. Extract a shared helper around _wait_for_sync_runs that
classifies sync statuses once (timeout, any failed, not all ingested) and
returns or raises consistently, then have
_prepare_changed_sources_for_maintenance and _trigger_for_kg call it and map the
result to their respective error handling (_ValueError_ vs _fail_latest_run_).
Use the existing symbols _prepare_changed_sources_for_maintenance,
_trigger_for_kg, and _wait_for_sync_runs to keep both paths aligned.
src/api/tests/unit/management/application/test_maintenance_pipeline_service.py (1)

882-929: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Prepare path fully mocked — no coverage for timeout/failed/unexpected-state branches.

_prepare_changed_sources_for_maintenance is replaced with a bare AsyncMock(), so the new ValueError branches in that method (timeout, failed sync, unexpected terminal state — Lines 268-276 in maintenance_pipeline_service.py) are untested. Given TDD is mandated for this repo, add at least one test asserting regenerate_maintenance_jobs propagates the ValueError when prepare fails.

As per coding guidelines, "OF UTMOST IMPORTANCE: 100% adhere to TDD."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/api/tests/unit/management/application/test_maintenance_pipeline_service.py`
around lines 882 - 929, The `regenerate_maintenance_jobs` test fully mocks
`_prepare_changed_sources_for_maintenance`, so the new error branches in
`MaintenancePipelineService` are not covered. Add a test around
`regenerate_maintenance_jobs` that uses
`_prepare_changed_sources_for_maintenance` on `MaintenancePipelineService` to
raise the `ValueError` for a failed prepare path (timeout/failed/unexpected
terminal state) and assert the exception is propagated instead of continuing to
`_build_maintenance_jobs`. Keep the existing happy-path test and add this
failure-path coverage using the same `svc`, `prepare`, and
`job_repo.sync_maintenance_pending_jobs` setup.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/verify-fleet-apps-kartograph.sh`:
- Around line 10-13: The verify script uses a predictable shared /tmp directory
for WORKDIR, which is vulnerable to symlink-planting and path hijacking. Update
the setup in verify-fleet-apps-kartograph.sh so the WORKDIR is created with a
unique temporary directory (for example via mktemp) instead of a fixed default
path, and keep the existing mkdir/cd flow operating on that safely created
directory. Ensure the new temp directory is used consistently by the git
clone/reset logic in this script.

In `@scripts/verify-vault-extraction-runtime.py`:
- Around line 233-239: The stdout summary in the ADC verification path is
exposing secret-derived data from the Vault-sourced JSON, so update the printing
logic around adc parsing to avoid logging any tainted fields. In
verify-vault-extraction-runtime.py, adjust the block that uses adc.get(...) so
it no longer prints project_id (and keep the ADC output fully redacted or
limited to non-sensitive metadata like type only if safe), or add an explicit
justified suppression if that’s the chosen approach.

In `@src/api/scripts/api-entrypoint-openshift.sh`:
- Around line 18-20: The gateway setup in the openshift entrypoint only checks
whether a registration exists, so it can skip re-adding a stale endpoint. Update
the logic around the openshell gateway info / gateway add flow to inspect the
currently registered gateway URL and compare it with
KARTOGRAPH_EXTRACTION_RUNTIME_OPENSHELL_GATEWAY_URL, then call openshell gateway
add again whenever the stored URL differs. Keep the change localized to the
gateway_name/gateway_url registration block so the script re-registers
mismatched endpoints instead of assuming existence is enough.

---

Outside diff comments:
In `@src/api/infrastructure/management/maintenance_pipeline_service.py`:
- Around line 205-214: The ingest-only launch path in MaintenancePipelineService
can create duplicate DataSourceSyncRun entries for the same source when
trigger/regenerate race. Update the per-source sync start flow in the relevant
helper that prepares ingest-only runs to first check for an existing active run
(pending or ingesting) or acquire a DB-backed lock before creating a new run.
Use the existing maintenance pipeline methods such as
_prepare_changed_sources_for_maintenance and the sync-run creation logic around
the ingest-only source loop to ensure only one ingest can start per data source
at a time.

---

Nitpick comments:
In `@src/api/infrastructure/management/maintenance_pipeline_service.py`:
- Around line 208-214: `regenerate_maintenance_jobs` currently blocks on
`_prepare_changed_sources_for_maintenance`, which can wait up to 300s via
`_wait_for_sync_runs` and time out synchronous request handlers. Refactor the
`needs_ingest` path in
`regenerate_maintenance_jobs`/`_prepare_changed_sources_for_maintenance` to
avoid long in-request polling by moving the wait-and-launch flow to an async
background job or returning immediately after enqueuing the ingest, and keep
`find_by_knowledge_graph`/`_changed_sources` refresh logic aligned with the new
non-blocking flow.
- Around line 252-277: The timeout/failed/unexpected-state classification logic
in _prepare_changed_sources_for_maintenance is duplicated with _trigger_for_kg
and should be centralized. Extract a shared helper around _wait_for_sync_runs
that classifies sync statuses once (timeout, any failed, not all ingested) and
returns or raises consistently, then have
_prepare_changed_sources_for_maintenance and _trigger_for_kg call it and map the
result to their respective error handling (_ValueError_ vs _fail_latest_run_).
Use the existing symbols _prepare_changed_sources_for_maintenance,
_trigger_for_kg, and _wait_for_sync_runs to keep both paths aligned.

In
`@src/api/tests/unit/management/application/test_maintenance_pipeline_service.py`:
- Around line 882-929: The `regenerate_maintenance_jobs` test fully mocks
`_prepare_changed_sources_for_maintenance`, so the new error branches in
`MaintenancePipelineService` are not covered. Add a test around
`regenerate_maintenance_jobs` that uses
`_prepare_changed_sources_for_maintenance` on `MaintenancePipelineService` to
raise the `ValueError` for a failed prepare path (timeout/failed/unexpected
terminal state) and assert the exception is propagated instead of continuing to
`_build_maintenance_jobs`. Keep the existing happy-path test and add this
failure-path coverage using the same `svc`, `prepare`, and
`job_repo.sync_maintenance_pending_jobs` setup.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: fc759d71-6800-41a8-80aa-482faac92337

📥 Commits

Reviewing files that changed from the base of the PR and between 2fccc95 and 94a0f7d.

⛔ Files ignored due to path filters (1)
  • src/api/uv.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • deploy/README.md
  • deploy/argocd/kartograph-stage.yaml
  • scripts/verify-fleet-apps-kartograph.sh
  • scripts/verify-vault-extraction-runtime.py
  • specs/extraction/maintenance-jobs.spec.md
  • src/api/infrastructure/management/maintenance_pipeline_service.py
  • src/api/scripts/api-entrypoint-openshift.sh
  • src/api/tests/unit/management/application/test_maintenance_pipeline_service.py
  • src/dev-ui/app/components/graph-management/GraphMaintenanceWorkspace.vue
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • openshift-hyperfleet/architecture (manual)
  • openshift-hyperfleet/hyperfleet-api (manual)
  • openshift-hyperfleet/hyperfleet-sentinel (manual)
  • openshift-hyperfleet/hyperfleet-adapter (manual)
  • openshift-hyperfleet/hyperfleet-broker (manual)

Comment thread scripts/verify-fleet-apps-kartograph.sh Outdated
Comment thread scripts/verify-vault-extraction-runtime.py
Comment thread src/api/scripts/api-entrypoint-openshift.sh Outdated
CodeQL (py/clear-text-logging-sensitive-data) flagged two high-severity
alerts in scripts/verify-vault-extraction-runtime.py: printing Vault
secret key names and ADC type/project_id values pulled directly from
the KV payload. Replace those with counts/booleans so no content
derived from the secret is ever echoed to stdout, and apply the same
redaction to the (unflagged but equivalent) extra-keys note and
_validate_adc error messages. Also drops two pre-existing ruff lints
(unused variable, redundant f-string) in the same file.

Co-authored-by: Cursor <cursoragent@cursor.com>
@aredenba-rh aredenba-rh changed the title Fix/ci fleet apps deploy tag fix(deploy): register openshell gateway CLI and sync GitOps docs to hp-fleet-gitops Jul 2, 2026
…entrypoint

- verify-fleet-apps-kartograph.sh: replace the predictable, fixed
  /tmp/kartograph-gitops-verify default WORKDIR with mktemp -d, closing
  a symlink-planting risk (CWE-377) since any local user/process could
  pre-create that path before the script clones/reset --hard's into it.
- api-entrypoint-openshift.sh: compare the openshell CLI's stored
  gateway_endpoint (read from its metadata.json) against
  KARTOGRAPH_EXTRACTION_RUNTIME_OPENSHELL_GATEWAY_URL before skipping
  `gateway add`, instead of only checking that a registration exists.
  Without this, a stale registration surviving in the emptyDir-backed
  XDG_CONFIG_HOME across container restarts could leave the pod pointed
  at an endpoint that no longer matches config.

Co-authored-by: Cursor <cursoragent@cursor.com>
@aredenba-rh aredenba-rh merged commit c5d8800 into main Jul 2, 2026
11 checks passed
@aredenba-rh aredenba-rh deleted the fix/ci-fleet-apps-deploy-tag branch July 2, 2026 04:14
aredenba-rh added a commit that referenced this pull request Jul 2, 2026
Reverts commit 2d76a14 (fix(ci): retarget Konflux deploy-tag to
fleet-apps on GitLab, #780). That change was correct at the time
(2026-06-30): ArgoCD read fleet-apps then. hp-gitops-tenants PR #9
(2026-07-01) repointed ArgoCD's kartograph-stage source at
hp-fleet-gitops (GitHub) instead, so the push pipelines' deploy-tag
finally task needs to target hp-fleet-gitops again — as it did before
#780, via the update-and-push + create-pull-request tasks (plain `git
push` + a `curl`-based GitHub PR creation step using the same `.netrc`
staged for git auth, since GitHub has no GitLab-style
`git push -o merge_request.*` equivalent).

Confirmed needed: both kartograph-api-on-push and
kartograph-dev-ui-on-push failed at update-deploy-tag on the first
push to main after merging #782, because it was still trying (and
failing) to push to the GitLab fleet-apps repo.

Requires the kartograph-hp-fleet-gitops-auth secret (GitHub PAT with
repo + pull_request scope) to exist in the kartograph-tenant Konflux
namespace — same requirement as before #780, when this last worked.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants