Repository navigation
OSAC-3557: Add AI-assisted development infrastructure to mono-repo #104
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| #!/bin/bash | ||
| # Project statusline: extends user statusline with osac + ai-workflows sync status | ||
| # Opt out: set CLAUDE_REPO_STATUSLINE_DISABLED=1 in .claude/settings.local.json env | ||
|
|
||
| input=$(cat) | ||
|
|
||
| if [[ "${CLAUDE_REPO_STATUSLINE_DISABLED:-}" == "1" ]]; then | ||
| exit 0 | ||
| fi | ||
|
|
||
| project_dir="${1:-}" | ||
|
|
||
| if command -v jq >/dev/null 2>&1 && [[ -f "${HOME}/.claude/settings.json" ]]; then | ||
| USER_STATUSLINE_CMD=$(jq -r '.statusLine.command // empty' "${HOME}/.claude/settings.json" 2>/dev/null) | ||
| if [[ -n "${USER_STATUSLINE_CMD}" ]]; then | ||
| printf "%s\n" "$input" | bash -c "${USER_STATUSLINE_CMD}" | ||
| fi | ||
| fi | ||
|
|
||
| GREEN='\033[32m' | ||
| YELLOW='\033[33m' | ||
| GRAY='\033[90m' | ||
| RESET='\033[0m' | ||
|
|
||
| log_info() { printf '%b%s%b' "$GREEN" "$1" "$RESET"; } | ||
| log_warning() { printf '%b%s%b' "$YELLOW" "$1" "$RESET"; } | ||
| log_muted() { printf '%b%s%b' "$GRAY" "$1" "$RESET"; } | ||
|
|
||
| repo_status() { | ||
| local dir="$1" name="$2" | ||
| [[ -d "$dir" ]] || { log_muted "$name: not found"; return; } | ||
|
|
||
| local branch behind | ||
| branch=$(git -C "$dir" branch --show-current 2>/dev/null) || branch="detached" | ||
| [[ -n "$branch" ]] || branch="detached" | ||
| behind=$(git -C "$dir" rev-list HEAD..origin/main --count 2>/dev/null) || { log_muted "$name: $branch ?"; return; } | ||
|
|
||
| if [[ "$behind" -eq 0 ]]; then | ||
| log_info "$name: $branch ✓" | ||
| else | ||
| log_warning "$name: $branch ↓${behind} behind" | ||
| fi | ||
| } | ||
|
|
||
| REPO_DIR="${project_dir:-$(printf '%s' "$input" | jq -r '.workspace.project_dir // empty' 2>/dev/null)}" | ||
| AI_DIR="${HOME}/.ai-workflows" | ||
|
|
||
| ws=$(repo_status "$REPO_DIR" "osac") | ||
| ai=$(repo_status "$AI_DIR" "ai-workflows") | ||
|
|
||
| printf '%b %b %b\n' "$ws" "${GRAY}|${RESET}" "$ai" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| #!/usr/bin/env bash | ||
| # SessionStart hook: fetch+rebase ai-workflows so the AI agent | ||
| # always has the latest skills and workflow phases. | ||
|
|
||
| fetch_and_rebase() { | ||
| local dir="$1" name="$2" | ||
| [[ -d "$dir" ]] || return 0 | ||
|
|
||
| if ! git -C "$dir" fetch origin -q 2>/dev/null; then | ||
| echo "$name: fetch failed" | ||
| return 0 | ||
| fi | ||
|
|
||
| local head_before head_after | ||
| head_before="$(git -C "$dir" rev-parse HEAD)" | ||
|
|
||
| trap 'git -C "$dir" rebase --abort 2>/dev/null || true' INT TERM | ||
|
|
||
| if git -C "$dir" rebase origin/main --autostash -q >/dev/null 2>&1; then | ||
| head_after="$(git -C "$dir" rev-parse HEAD)" | ||
| if [[ "$head_before" == "$head_after" ]]; then | ||
| echo "$name: up to date" | ||
| else | ||
| echo "$name: updated" | ||
| fi | ||
| else | ||
| git -C "$dir" rebase --abort 2>/dev/null || true | ||
| echo "$name: rebase conflict, skipped" | ||
| fi | ||
| trap - INT TERM | ||
| } | ||
|
|
||
| fetch_and_rebase "${HOME}/.ai-workflows" "ai-workflows" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| # Architecture Patterns | ||
|
|
||
| ## Multi-tenancy | ||
|
|
||
| Tenant-scoped resources include tenant isolation metadata: | ||
| - `metadata.annotations["osac.openshift.io/tenant"]` for tenant scoping | ||
| - `metadata.annotations["osac.openshift.io/owner-reference"]` for resource hierarchy | ||
| - OPA policies enforce isolation at runtime | ||
| - Never skip tenant isolation metadata in new tenant-scoped resources | ||
| - Use annotations for owner references, not separate fields | ||
| - Provider-defined resources (NetworkClass, ExternalIPPool) are exempt — tenants do not interact with them directly | ||
|
|
||
| ## Resource Hierarchy | ||
|
|
||
| ```text | ||
| Cluster Resources: | ||
| ClusterOrder → provisions OpenShift clusters via Hosted Control Planes | ||
|
|
||
| Compute Resources: | ||
| ComputeInstance → KubeVirt VM, attached to Subnets + SecurityGroups | ||
|
|
||
| Networking Resources: | ||
| NetworkClass (platform-defined, read-only for tenants) | ||
| └── VirtualNetwork (tenant L2 network with CIDR) | ||
| ├── Subnet (CIDR range within VirtualNetwork) | ||
| ├── SecurityGroup (firewall rules scoped to VirtualNetwork) | ||
| └── NATGateway (SNATs egress traffic through an ExternalIP) | ||
|
|
||
| External IP Resources: | ||
| ExternalIPPool (platform-defined, external IP ranges) | ||
| ├── ExternalIP (allocated from pool) | ||
| └── ExternalIPAttachment (binds ExternalIP to ComputeInstance) | ||
|
|
||
| Tenant Resources: | ||
| Tenant → namespace and resource isolation | ||
| ``` | ||
|
|
||
| Parent-child relationships use owner reference annotations (`osac.openshift.io/owner-reference`). | ||
|
|
||
| ## Service Stack (fulfillment-service) | ||
|
|
||
| - PostgreSQL for persistent storage | ||
| - gRPC with grpc-gateway for REST/JSON support | ||
| - Controller-runtime for Kubernetes integration | ||
| - OPA for authorization policies | ||
| - Prometheus for metrics | ||
|
|
||
| ## Integration Testing (fulfillment-service) | ||
|
|
||
| - Kind clusters (named "fulfillment-service-it") | ||
| - TLS with SNI routing via Envoy Gateway | ||
| - Keycloak for authentication | ||
| - Requires `/etc/hosts` entries: | ||
| - `127.0.0.1 keycloak.keycloak.svc.cluster.local` | ||
| - `127.0.0.1 fulfillment-api.osac.svc.cluster.local` | ||
| - `127.0.0.1 fulfillment-internal-api.osac.svc.cluster.local` | ||
| - Use `IT_KEEP_KIND=true` to preserve cluster for debugging | ||
| - Clean up with: `kind delete cluster --name fulfillment-service-it` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| # CLI UX Guidelines | ||
|
|
||
| The OSAC CLI (`fulfillment-service/internal/cmd/cli/`) is a tenant-facing tool for managing infrastructure resources. It is NOT a Kubernetes admin tool - end users should not need to know k8s. | ||
|
|
||
| ## Design Inspiration | ||
|
|
||
| - **Primary reference**: kubectl - OSAC APIs are modeled after k8s, so the CLI naturally follows kubectl patterns | ||
| - **Per-feature reference**: when implementing new commands, also look at cloud CLIs (AWS, GCP, Rafay, VCD) for inspiration on how they solved the same problem | ||
| - The goal is not to copy any single CLI, but to use kubectl as the default and evaluate alternatives per-feature | ||
|
|
||
| ## Existing Verbs | ||
|
|
||
| `create`, `get`, `describe`, `edit`, `delete`, `annotate`, `label`, `login`, `logout`, `lookup`, `console`, `whoami`, `version` | ||
|
|
||
| ## When Adding New CLI Commands | ||
|
|
||
| - Check if kubectl has an equivalent command and follow its UX patterns | ||
| - If kubectl doesn't have one, survey cloud CLIs (az, gcloud, aws) for the closest equivalent | ||
| - Keep commands non-interactive and scriptable by default | ||
| - All new commands must work without assuming k8s knowledge from the user |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| # Networking Design Alignment | ||
|
|
||
| When working on networking-related tasks (Connectivity&Fabric component, networking resources like VirtualNetwork/Subnet/SecurityGroup/ExternalIP/NATGateway/NetworkClass, NICs, ports, interfaces, network attachments, VLANs, fabric/K8s managers, dispatcher, MetalLB, DNS, CIDR, DNAT/SNAT, peering, metering/QoS), read `.design/context/networking-decisions.md` before planning, implementing, or reviewing. For deep context, read the full designs linked from that file. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # Request Path Tracing | ||
|
|
||
| When designing or implementing features triggered by external requests (API endpoints, CLI commands), trace the request path from the user-facing entry point to the handler before writing code. List each layer the request passes through (REST gateway, gRPC interceptors, middleware, server). Any layer that transforms, filters, or routes the request is an affected component - even if its code doesn't change. | ||
|
|
||
| A layer that silently drops or ignores the feature's input is a bug that unit tests at the handler level won't catch. | ||
|
|
||
| ## OSAC Example | ||
|
|
||
| The fulfillment-service REST gateway uses grpc-gateway with `DefaultHeaderMatcher`, which only forwards permanent HTTP headers and `Grpc-Metadata-*` prefixed headers to gRPC metadata. Custom HTTP headers are silently dropped. When a feature relies on a custom header reaching the gRPC server, the gateway's header matcher configuration must be checked and updated. | ||
|
|
||
| Request path for REST API calls: | ||
|
|
||
| ```text | ||
| HTTP client → REST gateway (grpc-gateway mux) → gRPC interceptors → server handler | ||
| ``` | ||
|
|
||
| Check `fulfillment-service/internal/cmd/service/start/restgateway/start_rest_gateway_cmd.go` for gateway configuration when adding new headers. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| { | ||
| "permissions": { | ||
| "allow": [ | ||
| "Bash(date:*)", | ||
| "Bash(echo:*)", | ||
| "Bash(cat:*)", | ||
| "Bash(ls:*)", | ||
| "Bash(mkdir:*)", | ||
| "Bash(wc:*)", | ||
| "Bash(head:*)", | ||
| "Bash(tail:*)", | ||
| "Bash(sort:*)", | ||
| "Bash(grep:*)", | ||
| "Bash(tr:*)", | ||
| "Bash(git add:*)", | ||
| "Bash(git commit:*)", | ||
| "Bash(git status:*)", | ||
| "Bash(git log:*)", | ||
| "Bash(git diff:*)", | ||
| "Bash(git tag:*)", | ||
| "Bash(jira issue list:*)", | ||
| "Bash(jira issue view:*)" | ||
| ] | ||
| }, | ||
| "hooks": { | ||
| "SessionStart": [ | ||
| { | ||
| "hooks": [ | ||
| { | ||
| "type": "command", | ||
| "command": "bash \"${CLAUDE_PROJECT_DIR}/.claude/hooks/update-ai-context.sh\"", | ||
| "timeout": 20 | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| "statusLine": { | ||
| "type": "command", | ||
| "command": "input=$(cat); command -v jq >/dev/null || exit 0; dir=$(printf '%s' \"$input\" | jq -r '.workspace.project_dir'); [ -n \"$dir\" ] || exit 0; printf '%s' \"$input\" | bash \"$dir/.claude/hooks/statusline.sh\" \"$dir\"" | ||
| }, | ||
| "enabledPlugins": {} | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # OSAC Mono-Repo | ||
|
|
||
| OSAC (Open Sovereign AI Cloud) is a fulfillment system for provisioning Kubernetes clusters, compute instances, bare-metal hosts, and networking. This mono-repo contains six components, each with its own `CLAUDE.md`/`AGENTS.md` — **read the component's docs before making changes in it**. | ||
|
|
||
| ## Components | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
|
|
||
| | Component | Description | | ||
| |-----------|-------------| | ||
| | `fulfillment-service/` | gRPC/REST API server + `osac` CLI (PostgreSQL, OPA) | | ||
| | `osac-operator/` | Kubernetes operator for CRDs (ClusterOrder, ComputeInstance, Tenant, networking) | | ||
| | `osac-aap/` | Ansible playbooks for infrastructure provisioning | | ||
| | `osac-installer/` | Helm-based three-phase deployment orchestrator | | ||
| | `bare-metal-fulfillment-operator/` | Kubernetes operator for bare-metal host pools | | ||
| | `osac-csi-driver/` | CSI meta-driver aggregating vendor storage drivers | | ||
|
|
||
| ## External Repos | ||
|
|
||
| Clone as siblings for cross-repo workflows: | ||
|
|
||
| | Repo | Description | | ||
| |------|-------------| | ||
| | [osac-test-infra](https://github.com/osac-project/osac-test-infra) | E2E pytest tests against the fulfillment-service gRPC API | | ||
| | [osac-ui](https://github.com/osac-project/osac-ui) | Web console (React, PatternFly 6) | | ||
| | [enhancement-proposals](https://github.com/osac-project/enhancement-proposals) | PRDs and design documents (two-stage EP flow) | | ||
| | [docs](https://github.com/osac-project/docs) | Architecture docs and guides | | ||
|
|
||
| ## Cross-Component Changes | ||
|
|
||
| A feature spanning multiple components lands in a single branch and PR. Apply changes in dependency order: fulfillment-service (proto) → osac-operator (CRDs, controllers) → osac-aap (playbooks) → osac-installer (RBAC, Helm). For deployment coordination (image tags, submodules), see `osac-installer/AGENTS.md`. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| @AGENTS.md |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| #!/usr/bin/env bash | ||
| # Install AI workflow skills for this repo. | ||
| # | ||
| # Usage: tools/bootstrap.sh | ||
| # | ||
| # This script: | ||
| # 1. Clones or updates flightctl/ai-workflows (prefers ~/.ai-workflows) | ||
| # 2. Installs workflows (bugfix, implement, prd, design, e2e) | ||
| # | ||
| # Re-run anytime to update to latest main. | ||
| set -euo pipefail | ||
|
|
||
| SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" | ||
| PROJECT_ROOT="$(realpath "${SCRIPT_DIR}/..")" | ||
|
|
||
| AI_WORKFLOWS_REPO="flightctl/ai-workflows" | ||
| AI_WORKFLOWS_DIR="" | ||
|
|
||
| # --- ai-workflows (flightctl) --- | ||
|
|
||
| if [[ -d "${HOME}/.ai-workflows" ]]; then | ||
| AI_WORKFLOWS_DIR="$(readlink -f "${HOME}/.ai-workflows")" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf 'Repo files matching bootstrap:\n'
fd -a 'bootstrap\.sh$' . | sed 's#^\./##'
printf '\nGit diff/stat if available:\n'
git diff --stat || true
printf '\ntools/bootstrap.sh outline and relevant lines:\n'
if [ -f tools/bootstrap.sh ]; then
wc -l tools/bootstrap.sh
sed -n '1,60p' tools/bootstrap.sh | cat -n
printf '\nOccurrences of readlink/realpath in tools/bootstrap.sh:\n'
rg -n 'readlink|realpath|AI_WORKFLOWS_DIR|AI_PROJECTS_DIR' tools/bootstrap.sh || true
fi
printf '\nSystem command availability/docs:\n'
command -v realpath || true
command -v readlink || true
( [ -x "$(command -v realpath)" ] && realpath --version 2>&1 | head -5 ) || true
( [ -x "$(command -v readlink)" ] && readlink --help 2>/dev/null | sed -n '1,12p' ) || trueRepository: osac-project/osac Length of output: 4823 Use
🤖 Prompt for AI Agents |
||
| echo "Updating ai-workflows (${AI_WORKFLOWS_DIR})..." | ||
| if ! (cd "$AI_WORKFLOWS_DIR" && git fetch origin -q); then | ||
| echo " Fetch failed for ai-workflows. Skipping update." | ||
| elif ! (cd "$AI_WORKFLOWS_DIR" && git rebase origin/main --autostash -q); then | ||
| (cd "$AI_WORKFLOWS_DIR" && git rebase --abort 2>/dev/null || true) | ||
| echo " Rebase failed for ai-workflows. Resolve manually: cd $AI_WORKFLOWS_DIR && git rebase origin/main" | ||
| else | ||
| echo " ai-workflows up to date" | ||
| fi | ||
| elif [[ -d "${PROJECT_ROOT}/.ai-workflows" ]]; then | ||
| AI_WORKFLOWS_DIR="${PROJECT_ROOT}/.ai-workflows" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's pretty much the same code as in lines 22-31, only with a different path. |
||
| echo "Updating ai-workflows (.ai-workflows)..." | ||
| if ! (cd "$AI_WORKFLOWS_DIR" && git fetch origin -q); then | ||
| echo " Fetch failed. Skipping update." | ||
| elif ! (cd "$AI_WORKFLOWS_DIR" && git rebase origin/main --autostash -q); then | ||
| (cd "$AI_WORKFLOWS_DIR" && git rebase --abort 2>/dev/null || true) | ||
| echo " Rebase failed. Resolve manually: cd $AI_WORKFLOWS_DIR && git rebase origin/main" | ||
| else | ||
| echo " ai-workflows up to date" | ||
| fi | ||
|
coderabbitai[bot] marked this conversation as resolved.
Resolved
|
||
| else | ||
| AI_WORKFLOWS_DIR="${PROJECT_ROOT}/.ai-workflows" | ||
| echo "Cloning ai-workflows..." | ||
| git clone "https://github.com/${AI_WORKFLOWS_REPO}.git" "${AI_WORKFLOWS_DIR}" | ||
| fi | ||
|
|
||
| echo "Installing ai-workflows skills..." | ||
| AI_WORKFLOWS="bugfix,implement,prd,design,e2e" | ||
| "${AI_WORKFLOWS_DIR}/install.sh" all --project "${PROJECT_ROOT}" --workflows "${AI_WORKFLOWS}" | ||
|
|
||
| echo "" | ||
| echo "AI workflows installed." | ||
Uh oh!
There was an error while loading. Please reload this page.