|
| 1 | +# GitHub Copilot Instructions — meshstack-hub |
| 2 | + |
| 3 | +## Purpose of this Repository |
| 4 | + |
| 5 | +The meshstack-hub is the **canonical Terraform module registry** for meshStack integrations — an |
| 6 | +Artifactory-like catalog with a UI at hub.meshcloud.io. It is the **monorepo for all IaC |
| 7 | +building blocks** that can be imported into any meshStack instance. |
| 8 | + |
| 9 | +> CI runs `tf validate` and `terraform-docs` on every module — it does **not** run `tf plan`. |
| 10 | +> Planning and applying happens in IaC runtimes (LCF/ICF) that consume modules from this repo. |
| 11 | +
|
| 12 | +--- |
| 13 | + |
| 14 | +## Module Structure |
| 15 | + |
| 16 | +Every module follows a strict two-tier layout: |
| 17 | + |
| 18 | +``` |
| 19 | +modules/<cloud-provider>/<service-name>/ |
| 20 | +├── backplane/ # Infrastructure/permissions setup (run by platform team) |
| 21 | +│ ├── main.tf |
| 22 | +│ ├── variables.tf |
| 23 | +│ ├── outputs.tf |
| 24 | +│ ├── versions.tf |
| 25 | +│ └── README.md |
| 26 | +├── buildingblock/ # Actual service resources (run by meshStack per tenant) |
| 27 | +│ ├── main.tf |
| 28 | +│ ├── variables.tf |
| 29 | +│ ├── outputs.tf |
| 30 | +│ ├── versions.tf |
| 31 | +│ ├── provider.tf |
| 32 | +│ ├── README.md # YAML front-matter required (see below) |
| 33 | +│ ├── APP_TEAM_README.md # User-facing docs with shared responsibility matrix |
| 34 | +│ ├── logo.png |
| 35 | +│ └── *.tftest.hcl |
| 36 | +└── meshstack_integration.tf # Example wiring into a meshStack instance |
| 37 | +``` |
| 38 | + |
| 39 | +--- |
| 40 | + |
| 41 | +## `meshstack_integration.tf` Conventions |
| 42 | + |
| 43 | +These files are **examples** showing how to register a module in a meshStack instance. |
| 44 | +They are starting points to be adapted, not production configs. |
| 45 | + |
| 46 | +### Shared variable conventions |
| 47 | + |
| 48 | +All `meshstack_integration.tf` files must use a consistent set of `variable` blocks so that |
| 49 | +IaC runtimes (LCF/ICF) can wire them together uniformly. Use structured `object({})` types to |
| 50 | +group related variables: |
| 51 | + |
| 52 | +```hcl |
| 53 | +# Shared Hub reference — always include this variable |
| 54 | +variable "hub" { |
| 55 | + type = object({ |
| 56 | + git_ref = string |
| 57 | + }) |
| 58 | + default = { |
| 59 | + git_ref = "main" |
| 60 | + } |
| 61 | + description = "Hub release reference. Set git_ref to a tag (e.g. 'v1.2.3') or branch for the meshstack-hub repo." |
| 62 | +} |
| 63 | +
|
| 64 | +# Shared meshStack context — always include this variable |
| 65 | +variable "meshstack" { |
| 66 | + type = object({ |
| 67 | + owning_workspace_identifier = string |
| 68 | + }) |
| 69 | + description = "Shared meshStack context passed down from the IaC runtime." |
| 70 | +} |
| 71 | +``` |
| 72 | + |
| 73 | +Use these variables in the implementation block: |
| 74 | + |
| 75 | +```hcl |
| 76 | +implementation = { |
| 77 | + terraform = { |
| 78 | + repository_url = "https://github.com/meshcloud/meshstack-hub.git" |
| 79 | + repository_path = "modules/<provider>/<service>/buildingblock" |
| 80 | + ref_name = var.hub.git_ref # always use var.hub.git_ref, never hardcode "main" |
| 81 | + } |
| 82 | +} |
| 83 | +
|
| 84 | +resource "meshstack_building_block_definition" "this" { |
| 85 | + metadata = { |
| 86 | + owned_by_workspace = var.meshstack.owning_workspace_identifier |
| 87 | + } |
| 88 | + ... |
| 89 | +} |
| 90 | +``` |
| 91 | + |
| 92 | +You may extend `variable "hub"` with additional fields as needed (e.g. `base_url`), but `git_ref` |
| 93 | +is always required. |
| 94 | + |
| 95 | +### Backplane module reference |
| 96 | + |
| 97 | +Always reference the backplane with a **relative path**: |
| 98 | + |
| 99 | +```hcl |
| 100 | +module "backplane" { |
| 101 | + source = "./backplane" |
| 102 | + # ... |
| 103 | +} |
| 104 | +``` |
| 105 | + |
| 106 | +### ❌ Avoid these patterns |
| 107 | + |
| 108 | +```hcl |
| 109 | +# ❌ locals instead of variables — makes values non-configurable by runtimes |
| 110 | +locals { |
| 111 | + owning_workspace_identifier = "my-workspace" |
| 112 | + github_org = "my-org" |
| 113 | +} |
| 114 | +
|
| 115 | +# ❌ provider blocks inside mesh_integration.tf — the Hub UI renders these |
| 116 | +provider "meshstack" { ... } |
| 117 | +
|
| 118 | +# ❌ absolute GitHub source URL in module block — use relative path instead |
| 119 | +module "backplane" { |
| 120 | + source = "github.com/meshcloud/meshstack-hub//modules/aws/s3_bucket/backplane?ref=main" |
| 121 | +} |
| 122 | +
|
| 123 | +# ❌ standalone meshstack_hub_git_ref variable — use variable "hub" { type = object({git_ref=string}) } instead |
| 124 | +variable "meshstack_hub_git_ref" { ... } |
| 125 | +
|
| 126 | +# ❌ hardcoded ref — always use var.hub.git_ref |
| 127 | +ref_name = "main" |
| 128 | +``` |
| 129 | + |
| 130 | +--- |
| 131 | + |
| 132 | +## Backplane Patterns |
| 133 | + |
| 134 | +**AWS:** IAM users + CloudFormation StackSets for cross-account roles; assume role for target account access. |
| 135 | + |
| 136 | +**Azure:** |
| 137 | +- Custom role definitions scoped to subscription or management group |
| 138 | +- Optional service principal creation with Workload Identity Federation (WIF); falls back to app password |
| 139 | +- Two-tier networking roles: `buildingblock_deploy` (main) and `buildingblock_deploy_hub` (VNet peering, ACR, Key Vault) |
| 140 | + |
| 141 | +--- |
| 142 | + |
| 143 | +## Variable Conventions |
| 144 | + |
| 145 | +- Always use `snake_case` for variable names: `monthly_budget_amount`, not `monthlyBudgetAmount` |
| 146 | +- Group logically related inputs into `object({})` typed variables (e.g. `var.hub`, `var.meshstack`) |
| 147 | +- Pin provider versions with `~> X.Y.Z` (allow patch updates, not minor/major) |
| 148 | +- Terraform baseline: `>= 1.3.0` |
| 149 | + |
| 150 | +--- |
| 151 | + |
| 152 | +## Documentation Requirements |
| 153 | + |
| 154 | +**`buildingblock/README.md`** — must include YAML front-matter: |
| 155 | + |
| 156 | +```yaml |
| 157 | +--- |
| 158 | +name: <Human-readable name> |
| 159 | +supportedPlatforms: |
| 160 | + - <platform-id> # e.g. aws, azure, stackit |
| 161 | +description: One-sentence description of what the module provisions. |
| 162 | +--- |
| 163 | +``` |
| 164 | + |
| 165 | +**`buildingblock/APP_TEAM_README.md`** — user-facing; must include: |
| 166 | +- What the building block does and when to use it |
| 167 | +- Usage examples |
| 168 | +- Shared responsibility matrix (platform team vs. application team) |
| 169 | +- Best practices |
| 170 | + |
| 171 | +--- |
| 172 | + |
| 173 | +## Testing |
| 174 | + |
| 175 | +Test files (`.tftest.hcl`) must cover: |
| 176 | +- Positive scenarios (valid configurations) |
| 177 | +- Negative scenarios (invalid inputs / validation rules) |
| 178 | +- Naming collision prevention |
| 179 | + |
| 180 | +Standard test users (use these identifiers consistently): |
| 181 | + |
| 182 | +```hcl |
| 183 | +{ meshIdentifier = "likvid-tom-user", username = "likvid-tom@meshcloud.io", roles = ["admin", "Workspace Owner"] } |
| 184 | +{ meshIdentifier = "likvid-daniela-user", username = "likvid-daniela@meshcloud.io", roles = ["user", "Workspace Manager"] } |
| 185 | +{ meshIdentifier = "likvid-anna-user", username = "likvid-anna@meshcloud.io", roles = ["reader", "Workspace Member"] } |
| 186 | +``` |
| 187 | + |
| 188 | +--- |
| 189 | + |
| 190 | +## STACKIT-Specific Notes |
| 191 | + |
| 192 | +- STACKIT Git is based on Forgejo/Gitea — use the Gitea provider, not a generic Git provider |
| 193 | +- Forgejo/Gitea **user management** (org membership, team assignments) must be handled in the |
| 194 | + backplane; it is currently incomplete in the STACKIT git-repository module |
| 195 | +- The STACKIT project building block (`modules/stackit/project/`) is the mandatory Landing Zone |
| 196 | + building block and should be the first dependency for any STACKIT composition |
| 197 | + |
| 198 | +--- |
| 199 | + |
| 200 | +## Hub as a Shim for IaC Runtimes |
| 201 | + |
| 202 | +Modules in this repo are **consumed** by IaC runtimes (LCF, ICF, customer deployments). |
| 203 | +Those runtimes are shim layers — they reference Hub modules and should not re-implement logic here. |
| 204 | + |
| 205 | +When prototyping locally in an IaC runtime, use relative module includes to avoid constant |
| 206 | +branch pushes: |
| 207 | + |
| 208 | +```hcl |
| 209 | +# In LCF/ICF terragrunt.hcl — for local prototyping only |
| 210 | +source = "../../../meshstack-hub/modules/stackit/git-repository/buildingblock" |
| 211 | +``` |
| 212 | + |
| 213 | +Do **not** commit these relative paths; switch back to the Hub GitHub URL before merging. |
| 214 | + |
| 215 | +--- |
| 216 | + |
| 217 | +## Checklist for New Modules |
| 218 | + |
| 219 | +- [ ] `backplane/` and `buildingblock/` with all required files |
| 220 | +- [ ] Provider versions pinned with `~>` |
| 221 | +- [ ] Variables in `snake_case` |
| 222 | +- [ ] `buildingblock/README.md` with YAML front-matter |
| 223 | +- [ ] `buildingblock/APP_TEAM_README.md` with shared responsibility matrix |
| 224 | +- [ ] `meshstack_integration.tf` uses `variable "hub" { type = object({git_ref = string}) }` and `variable "meshstack" { type = object({owning_workspace_identifier = string}) }` |
| 225 | +- [ ] `meshstack_integration.tf` uses relative `./backplane` source (no absolute GitHub URL) |
| 226 | +- [ ] `ref_name` uses `var.hub.git_ref` — no hardcoded `"main"` |
| 227 | +- [ ] No `provider` blocks in `meshstack_integration.tf` |
| 228 | +- [ ] Test file covering positive, negative, and naming collision scenarios |
| 229 | +- [ ] `logo.png` included in `buildingblock/` |
| 230 | +- [ ] No trailing whitespace |
0 commit comments