diff --git a/devfile.yaml b/devfile.yaml index 67889af..b6357c5 100644 --- a/devfile.yaml +++ b/devfile.yaml @@ -61,6 +61,11 @@ components: protocol: https name: quarkus-debug targetPort: 5005 +- name: tools + container: + image: quay.io/devfile/universal-developer-image:ubi10-latest + mountSources: true + memoryLimit: 4G - volume: size: 10Gi name: projects @@ -104,6 +109,65 @@ commands: component: dev-tools workingDir: "${PROJECTS_ROOT}/dev-workspace" id: init-env +- id: gcloud-init + exec: + label: "1. Google Cloud CLI - Initialization" + commandLine: gcloud init --console-only + component: tools + +- id: gcloud-auth-login + exec: + label: "2. Google Cloud CLI - Set up default authentication" + commandLine: gcloud auth application-default login --no-launch-browser + component: tools + +- id: gcloud-auth-set-quota-project + exec: + label: "3. Google Cloud CLI - Set Quota Project" + commandLine: gcloud auth application-default set-quota-project cloudability-it-gemini + component: tools + +- id: create-gcloud-adc-secret + exec: + label: "4. Create Google Cloud ADC Secret" + commandLine: | + kubectl create secret generic gcloud-adc --from-file=adc.json=$HOME/.config/gcloud/application_default_credentials.json && \ + kubectl label secret gcloud-adc controller.devfile.io/mount-to-devworkspace=true controller.devfile.io/watch-secret=true --overwrite + component: tools + +- id: annotate-gcloud-adc-secret + exec: + label: "5. Annotate Google Cloud ADC Secret" + commandLine: | + kubectl annotate secret gcloud-adc controller.devfile.io/mount-path=/credentials controller.devfile.io/mount-as=file --overwrite + component: tools + +- id: setup-environment-variables + exec: + label: "6. Set up environment variables ConfigMap" + commandLine: | + source scripts/setup-claude-vertex-env.sh + component: dev-tools + +- id: annotate-environment-variables + exec: + label: "7. Annotate environment variables ConfigMap" + commandLine: | + kubectl annotate configmap ai-tools-env controller.devfile.io/mount-as=env --overwrite + component: tools + +- id: install-claude + exec: + label: 8. Install Claude CLI (Optional) + commandLine: curl -fsSL https://claude.ai/install.sh -o claude-install.sh && chmod +x claude-install.sh && ./claude-install.sh + component: tools + +- id: add-dataverse-mcp + exec: + label: 9. Add Dataverse MCP (Optional) + commandLine: claude mcp add --transport http dataverse https://mcp.dataverse.redhat.com/mcp/ + component: tools + events: preStart: - cp-oc-cli diff --git a/pelorus.code-workspace b/pelorus.code-workspace index f58bafd..c249b65 100644 --- a/pelorus.code-workspace +++ b/pelorus.code-workspace @@ -19,6 +19,7 @@ ], "extensions": { "recommendations": [ + "anthropic.claude-code", "redhat.vscode-yaml", "redhat.java", "redhat.vscode-quarkus", diff --git a/scripts/setup-claude-vertex-env.sh b/scripts/setup-claude-vertex-env.sh new file mode 100755 index 0000000..7400d3d --- /dev/null +++ b/scripts/setup-claude-vertex-env.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +# Sets Claude Code / Vertex AI environment variables. +# Usage: source scripts/setup-claude-vertex-env.sh +# If GCP_PROJECT_ID is unset, you are prompted to enter it (interactive terminal). + +#set -euo pipefail + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + echo "Source this script so exports apply in your current shell: source ${BASH_SOURCE[0]}" >&2 + exit 1 +fi + +if [[ -z "${GCP_PROJECT_ID:-}" ]]; then + if [[ -t 0 ]]; then + read -r -p "Enter GCP project ID: " GCP_PROJECT_ID + GCP_PROJECT_ID="${GCP_PROJECT_ID#"${GCP_PROJECT_ID%%[![:space:]]*}"}" + GCP_PROJECT_ID="${GCP_PROJECT_ID%"${GCP_PROJECT_ID##*[![:space:]]}"}" + elif command -v gcloud &>/dev/null; then + GCP_PROJECT_ID="$(gcloud config get-value project 2>/dev/null || true)" + if [[ -z "${GCP_PROJECT_ID}" || "${GCP_PROJECT_ID}" == "(unset)" ]]; then + echo "Set GCP_PROJECT_ID, or run this script in a terminal to enter it interactively." >&2 + return 1 + fi + else + echo "Set GCP_PROJECT_ID, or run this script in a terminal to enter it interactively." >&2 + return 1 + fi +fi + +if [[ -z "${GCP_PROJECT_ID}" || "${GCP_PROJECT_ID}" == "(unset)" ]]; then + echo "GCP_PROJECT_ID cannot be empty." >&2 + return 1 +fi + +export GCP_PROJECT_ID +export GOOGLE_APPLICATION_CREDENTIALS=/credentials/adc.json +export CLAUDE_CODE_USE_VERTEX=1 +export CLOUD_ML_REGION=global +export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 +export ANTHROPIC_VERTEX_PROJECT_ID="${GCP_PROJECT_ID}" + +echo "Environment variables set:" +echo "export GCP_PROJECT_ID=${GCP_PROJECT_ID}" +echo "export GOOGLE_APPLICATION_CREDENTIALS=${GOOGLE_APPLICATION_CREDENTIALS}" +echo "export CLAUDE_CODE_USE_VERTEX=${CLAUDE_CODE_USE_VERTEX}" +echo "export CLOUD_ML_REGION=${CLOUD_ML_REGION}" +echo "export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=${CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC}" +echo "export ANTHROPIC_VERTEX_PROJECT_ID=${ANTHROPIC_VERTEX_PROJECT_ID}" + +kubectl create configmap ai-tools-env \ + --from-literal=GOOGLE_APPLICATION_CREDENTIALS=/credentials/adc.json \ + --from-literal=CLAUDE_CODE_USE_VERTEX=1 \ + --from-literal=ANTHROPIC_VERTEX_PROJECT_ID=${GCP_PROJECT_ID} \ + --from-literal=ANTHROPIC_VERTEX_REGION=${CLOUD_ML_REGION} \ + --from-literal=CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \ + --dry-run=client -o yaml | kubectl apply -f - + +kubectl label configmap ai-tools-env \ + controller.devfile.io/mount-to-devworkspace=true \ + controller.devfile.io/watch-configmap=true \ + --overwrite