diff --git a/azure/1-infra.sh b/azure/1-infra.sh index 0f46c7bb..3bfdb4aa 100755 --- a/azure/1-infra.sh +++ b/azure/1-infra.sh @@ -20,15 +20,15 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # ── Carregar configuració ───────────────────────────────────────────────────── -#CONFIG_FILE="${SCRIPT_DIR}/config.sh" -#if [[ ! -f "$CONFIG_FILE" ]]; then -# echo "ERROR: No s'ha trobat azure/config.sh" -# echo " Còpia l'exemple: cp azure/config.sh.example azure/config.sh" -# echo " Després omple els valors i torna a executar." -# exit 1 -#fi +CONFIG_FILE="${SCRIPT_DIR}/config.sh" +if [[ ! -f "$CONFIG_FILE" ]]; then + echo "ERROR: No s'ha trobat azure/config.sh" + echo " Còpia l'exemple: cp azure/config.sh.example azure/config.sh" + echo " Després omple els valors i torna a executar." + exit 1 +fi # shellcheck source=config.sh.example -#source "$CONFIG_FILE" +source "$CONFIG_FILE" # ── Validar variables obligatòries ─────────────────────────────────────────── REQUIRED_VARS=( diff --git a/azure/2-build-deploy.sh b/azure/2-build-deploy.sh index 9de2c7d4..a08f2f80 100755 --- a/azure/2-build-deploy.sh +++ b/azure/2-build-deploy.sh @@ -17,14 +17,14 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" # ── Carregar configuració ───────────────────────────────────────────────────── -#CONFIG_FILE="${SCRIPT_DIR}/config.sh" -#if [[ ! -f "$CONFIG_FILE" ]]; then -# echo "ERROR: No s'ha trobat azure/config.sh" -# echo " Còpia l'exemple: cp azure/config.sh.example azure/config.sh" -# exit 1 -#fi +CONFIG_FILE="${SCRIPT_DIR}/config.sh" +if [[ ! -f "$CONFIG_FILE" ]]; then + echo "ERROR: No s'ha trobat azure/config.sh" + echo " Còpia l'exemple: cp azure/config.sh.example azure/config.sh" + exit 1 +fi # shellcheck source=config.sh.example -#source "$CONFIG_FILE" +source "$CONFIG_FILE" # ── Validar variables obligatòries ─────────────────────────────────────────── REQUIRED_VARS=( @@ -97,6 +97,7 @@ az acr login --name "$ACR_NAME" # ── Build de la imatge Docker ───────────────────────────────────────────────── echo "→ Build de la imatge Docker..." docker build \ + ${NO_CACHE:+--no-cache} \ --tag "$FULL_IMAGE" \ --tag "$LATEST_IMAGE" \ "$REPO_ROOT" diff --git a/azure/container-app.bicep b/azure/container-app.bicep index 408606a5..4122fe62 100644 --- a/azure/container-app.bicep +++ b/azure/container-app.bicep @@ -107,6 +107,45 @@ param reportAgentMaxReflectionRounds string = '2' @description('Temperatura del model LLM per al Report Agent') param reportAgentTemperature string = '0.5' +// ─── Secrets i env vars condicionals (Azure rebutja secrets amb valor buit) ─── +var mandatorySecrets = [ + { name: 'acr-password', value: acrPassword } + { name: 'demo-password', value: demoPassword } + { name: 'llm-api-key', value: llmApiKey } + { name: 'secret-key', value: secretKey } +] +var optionalSecrets = concat( + empty(llmBoostApiKey) ? [] : [{ name: 'llm-boost-api-key', value: llmBoostApiKey }], + empty(zepApiKey) ? [] : [{ name: 'zep-api-key', value: zepApiKey }], + empty(neo4jPassword) ? [] : [{ name: 'neo4j-password', value: neo4jPassword }] +) +var allSecrets = concat(mandatorySecrets, optionalSecrets) + +var mandatoryEnv = [ + { name: 'DEMO_PASSWORD', secretRef: 'demo-password' } + { name: 'LLM_API_KEY', secretRef: 'llm-api-key' } + { name: 'SECRET_KEY', secretRef: 'secret-key' } + { name: 'LLM_BASE_URL', value: llmBaseUrl } + { name: 'LLM_MODEL_NAME', value: llmModelName } + { name: 'LLM_PROVIDER', value: llmProvider } + { name: 'LLM_BOOST_BASE_URL', value: llmBoostBaseUrl } + { name: 'LLM_BOOST_MODEL_NAME', value: llmBoostModelName } + { name: 'GRAPH_BACKEND', value: graphBackend } + { name: 'NEO4J_URI', value: neo4jUri } + { name: 'NEO4J_USER', value: neo4jUser } + { name: 'OASIS_DEFAULT_MAX_ROUNDS', value: oasisDefaultMaxRounds } + { name: 'REPORT_AGENT_MAX_TOOL_CALLS', value: reportAgentMaxToolCalls } + { name: 'REPORT_AGENT_MAX_REFLECTION_ROUNDS', value: reportAgentMaxReflectionRounds } + { name: 'REPORT_AGENT_TEMPERATURE', value: reportAgentTemperature } + { name: 'FLASK_DEBUG', value: 'False' } +] +var optionalEnv = concat( + empty(llmBoostApiKey) ? [] : [{ name: 'LLM_BOOST_API_KEY', secretRef: 'llm-boost-api-key' }], + empty(zepApiKey) ? [] : [{ name: 'ZEP_API_KEY', secretRef: 'zep-api-key' }], + empty(neo4jPassword) ? [] : [{ name: 'NEO4J_PASSWORD', secretRef: 'neo4j-password' }] +) +var allEnv = concat(mandatoryEnv, optionalEnv) + // ─── Container App ───────────────────────────────────────────────────────────── resource containerApp 'Microsoft.App/containerApps@2023-05-01' = { name: projectName @@ -115,16 +154,7 @@ resource containerApp 'Microsoft.App/containerApps@2023-05-01' = { managedEnvironmentId: containerAppsEnvId configuration: { - // Secrets: credencials ACR + variables sensibles de l'aplicació - secrets: [ - { name: 'acr-password', value: acrPassword } - { name: 'demo-password', value: demoPassword } - { name: 'llm-api-key', value: llmApiKey } - { name: 'llm-boost-api-key', value: llmBoostApiKey } - { name: 'zep-api-key', value: zepApiKey } - { name: 'neo4j-password', value: neo4jPassword } - { name: 'secret-key', value: secretKey } - ] + secrets: allSecrets // Credencials del registre privat (ACR) registries: [ @@ -155,39 +185,7 @@ resource containerApp 'Microsoft.App/containerApps@2023-05-01' = { { name: projectName image: containerImage - - env: [ - // ── Secrets referenciats per nom (mai valor en text pla) ── - { name: 'DEMO_PASSWORD', secretRef: 'demo-password' } - { name: 'LLM_API_KEY', secretRef: 'llm-api-key' } - { name: 'LLM_BOOST_API_KEY', secretRef: 'llm-boost-api-key' } - { name: 'ZEP_API_KEY', secretRef: 'zep-api-key' } - { name: 'NEO4J_PASSWORD', secretRef: 'neo4j-password' } - { name: 'SECRET_KEY', secretRef: 'secret-key' } - - // ── Variables no sensibles ── - { name: 'LLM_BASE_URL', value: llmBaseUrl } - { name: 'LLM_MODEL_NAME', value: llmModelName } - { name: 'LLM_PROVIDER', value: llmProvider } - { name: 'LLM_BOOST_BASE_URL', value: llmBoostBaseUrl } - { name: 'LLM_BOOST_MODEL_NAME', value: llmBoostModelName } - - // ── Backend de graf ── - { name: 'GRAPH_BACKEND', value: graphBackend } - { name: 'NEO4J_URI', value: neo4jUri } - { name: 'NEO4J_USER', value: neo4jUser } - - // ── Simulació OASIS ── - { name: 'OASIS_DEFAULT_MAX_ROUNDS', value: oasisDefaultMaxRounds } - - // ── Report Agent ── - { name: 'REPORT_AGENT_MAX_TOOL_CALLS', value: reportAgentMaxToolCalls } - { name: 'REPORT_AGENT_MAX_REFLECTION_ROUNDS', value: reportAgentMaxReflectionRounds } - { name: 'REPORT_AGENT_TEMPERATURE', value: reportAgentTemperature } - - // ── Flask ── - { name: 'FLASK_DEBUG', value: 'False' } - ] + env: allEnv // Recursos mínim viable — escalar horitzontalment via rèpliques resources: {