Skip to content

feat: extract shared azd hooks and Terraform modules for org-wide reuse #8

@rsalus

Description

@rsalus

Summary

Standardize azd hooks, Terraform modules, and deployment scripts across the lvlup-sw org. Currently, each platform repo (basileus, ares-elite-platform) maintains its own copy of deployment infrastructure. This creates drift and duplicated maintenance.

Context

We already share:

  • GitHub Actions workflows — 8 reusable workflows in .github/workflows/
  • Runner infrastructure.github/infra/runners/
  • Build standardslvlup-build NuGet package

We do NOT share:

  • azd hooks (preprovision.sh, postprovision.sh, recover.sh, smoketest.sh)
  • Terraform modules (7 modules in basileus alone, likely reusable)
  • Deployment patterns (ACR image builds, Container App revision updates, Terraform state bootstrap)

Proposed Structure

.github/
├── infra/
│   ├── runners/           # (existing) Self-hosted GitHub runners
│   ├── modules/           # (new) Shared Terraform modules
│   │   ├── networking/    # VNet + subnets + NSGs + private DNS
│   │   ├── identity/      # Managed identity + Key Vault + RBAC
│   │   ├── container-apps/ # CAE + ACR + container apps
│   │   ├── data-services/ # PostgreSQL + Redis + private endpoints
│   │   └── monitoring/    # Log Analytics + DCR
│   └── hooks/             # (new) Shared azd hook library
│       ├── lib.sh         # Common functions (azd_get, try_import, etc.)
│       ├── bootstrap-backend.sh
│       ├── detect-deployer-ip.sh
│       ├── build-acr-images.sh
│       ├── force-revisions.sh
│       ├── smoketest-base.sh
│       └── rsync-excludes.txt

Approach (Three Layers)

1. Shared Terraform Modules via Git Source Refs

Extract reusable modules from basileus to .github/infra/modules/. Consumer repos reference by tag:

module "networking" {
  source = "git::https://github.com/lvlup-sw/.github.git//infra/modules/networking?ref=v1.0.0"
}

Version-pinned, no registry needed, free.

2. Shared Hook Scripts

Create a library of composable functions in .github/infra/hooks/. Consumer repos use thin wrapper scripts:

#!/usr/bin/env bash
source infra/shared/infra/hooks/lib.sh  # via git submodule
APP_NAME="basileus"
APPS=("agent-host" "control-plane" "inference-gateway")
bootstrap_backend "$APP_NAME"
terraform_init_and_apply

Consumer repos add .github as a git submodule at infra/shared.

3. Template Repo for New Projects (future)

lvlup-sw/aspire-template as a GitHub Template Repository with standard azure.yaml, module refs, and hook wrappers. One-time scaffold for new services.

azd Constraints

  • azure.yaml has no extends/inheritance mechanism
  • Hooks only support local file paths (no remote URL refs)
  • azd extensions (beta) can add commands but cannot inject hooks
  • Layered provisioning (beta) is within-repo only

These constraints drive the git-submodule + git-source-ref approach.

Modules to Extract from Basileus

Module Source Reusability
networking VNet, 4 subnets, 3 NSGs, private DNS High — any Azure app needs networking
identity Managed identity, Key Vault, RBAC, secrets High — standard identity pattern
container-apps CAE, ACR, container apps with lifecycle protection High — all Aspire apps use this
data-services PostgreSQL Flex, Redis, private endpoints High — common data tier
monitoring Log Analytics, DCR, VM extension Medium — useful for VM-based workloads
e2b-sandbox Linux VM, cloud-init, auto-shutdown Low — basileus-specific
bastion Azure Bastion (optional) Medium — debug/ops access

Tasks

  • Extract networking, identity, container-apps, data-services, monitoring modules to .github/infra/modules/
  • Create .github/infra/hooks/lib.sh with shared functions from basileus scripts
  • Create individual hook scripts (bootstrap-backend, build-acr-images, etc.)
  • Tag initial release (v1.0.0) for version pinning
  • Update basileus to consume shared modules via git source refs
  • Update ares-elite-platform to consume shared modules
  • Document the shared infrastructure pattern in .github/README.md

References

  • Basileus infra: lvlup-sw/basileus/infra/
  • Basileus issue #104 (Phronesis E2E validation)
  • Basileus issue #86 (runner capacity)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions