pipeline: add testing improvements for branch-based workflows
Some checks failed
Run nix flake check / flake-check (push) Has been cancelled
Some checks failed
Run nix flake check / flake-check (push) Has been cancelled
Implement dual improvements to enable efficient testing of pipeline changes without polluting master branch: 1. Add --force flag to create-host script - Skip hostname/IP uniqueness validation - Overwrite existing host configurations - Update entries in flake.nix and terraform/vms.tf (no duplicates) - Useful for iterating on configurations during testing 2. Add branch support to bootstrap mechanism - Bootstrap service reads NIXOS_FLAKE_BRANCH environment variable - Defaults to master if not set - Uses branch in git URL via ?ref= parameter - Service loads environment from /etc/environment 3. Add cloud-init disk support for branch configuration - VMs can specify flake_branch field in terraform/vms.tf - Automatically generates cloud-init snippet setting NIXOS_FLAKE_BRANCH - Uploads snippet to Proxmox via SSH - Production VMs omit flake_branch and use master 4. Update documentation - Document --force flag usage in create-host README - Add branch testing examples in terraform README - Update TODO.md with testing workflow - Add .generated/ to gitignore Testing workflow: Create feature branch, set flake_branch in VM definition, deploy with terraform, iterate with --force flag, clean up before merging. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -87,6 +87,21 @@ vms = {
|
||||
}
|
||||
```
|
||||
|
||||
### Example: Test VM with Custom Git Branch
|
||||
|
||||
For testing pipeline changes without polluting master:
|
||||
|
||||
```hcl
|
||||
vms = {
|
||||
"test-vm" = {
|
||||
ip = "10.69.13.100/24"
|
||||
flake_branch = "test-pipeline" # Bootstrap from this branch
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This VM will bootstrap from the `test-pipeline` branch instead of `master`. Production VMs should omit the `flake_branch` field.
|
||||
|
||||
## Configuration Options
|
||||
|
||||
Each VM in the `vms` map supports the following fields (all optional):
|
||||
@@ -98,6 +113,7 @@ Each VM in the `vms` map supports the following fields (all optional):
|
||||
| `cpu_cores` | Number of CPU cores | `2` |
|
||||
| `memory` | Memory in MB | `2048` |
|
||||
| `disk_size` | Disk size (e.g., "20G", "100G") | `"20G"` |
|
||||
| `flake_branch` | Git branch for bootstrap (for testing, omit for production) | `master` |
|
||||
| `target_node` | Proxmox node to deploy to | `"pve1"` |
|
||||
| `template_name` | Template VM to clone from | `"nixos-25.11.20260128.fa83fd8"` |
|
||||
| `storage` | Storage backend | `"local-zfs"` |
|
||||
@@ -182,9 +198,11 @@ deployment_summary = {
|
||||
- `main.tf` - Provider configuration
|
||||
- `variables.tf` - Variable definitions and defaults
|
||||
- `vms.tf` - VM definitions and deployment logic
|
||||
- `cloud-init.tf` - Custom cloud-init configuration for branch-specific bootstrap
|
||||
- `outputs.tf` - Output definitions for deployed VMs
|
||||
- `terraform.tfvars.example` - Example credentials file
|
||||
- `terraform.tfvars` - Your actual credentials (gitignored)
|
||||
- `.generated/` - Auto-generated cloud-init files (gitignored)
|
||||
- `vm.tf.old` - Archived single-VM configuration (reference)
|
||||
|
||||
## Notes
|
||||
|
||||
55
terraform/cloud-init.tf
Normal file
55
terraform/cloud-init.tf
Normal file
@@ -0,0 +1,55 @@
|
||||
# Cloud-init configuration for branch-specific bootstrap
|
||||
#
|
||||
# This file manages custom cloud-init snippets for VMs that need to bootstrap
|
||||
# from a specific git branch (non-master). Production VMs omit flake_branch
|
||||
# and use the default master branch.
|
||||
|
||||
# Generate cloud-init snippets for VMs with custom branch configuration
|
||||
resource "local_file" "cloud_init_branch" {
|
||||
for_each = {
|
||||
for name, vm in local.vm_configs : name => vm
|
||||
if vm.flake_branch != null
|
||||
}
|
||||
|
||||
filename = "${path.module}/.generated/cloud-init-${each.key}.yml"
|
||||
content = yamlencode({
|
||||
# Write NIXOS_FLAKE_BRANCH to /etc/environment
|
||||
# This will be read by bootstrap.nix service via EnvironmentFile
|
||||
write_files = [{
|
||||
path = "/etc/environment"
|
||||
content = "NIXOS_FLAKE_BRANCH=${each.value.flake_branch}\n"
|
||||
append = true
|
||||
}]
|
||||
})
|
||||
|
||||
file_permission = "0644"
|
||||
}
|
||||
|
||||
# Upload cloud-init snippets to Proxmox
|
||||
# Note: This requires SSH access to the Proxmox host
|
||||
# Alternative: Manually copy files or use Proxmox API if available
|
||||
resource "null_resource" "upload_cloud_init" {
|
||||
for_each = {
|
||||
for name, vm in local.vm_configs : name => vm
|
||||
if vm.flake_branch != null
|
||||
}
|
||||
|
||||
# Trigger re-upload when content changes
|
||||
triggers = {
|
||||
content_hash = local_file.cloud_init_branch[each.key].content
|
||||
}
|
||||
|
||||
# Upload the cloud-init file to Proxmox snippets directory
|
||||
provisioner "local-exec" {
|
||||
command = <<-EOT
|
||||
scp -o StrictHostKeyChecking=no \
|
||||
${local_file.cloud_init_branch[each.key].filename} \
|
||||
${var.proxmox_host}:/var/lib/vz/snippets/cloud-init-${each.key}.yml
|
||||
EOT
|
||||
}
|
||||
|
||||
depends_on = [local_file.cloud_init_branch]
|
||||
}
|
||||
|
||||
# Ensure VMs depend on cloud-init being uploaded
|
||||
# This is handled implicitly by the cicustom reference in vms.tf
|
||||
@@ -21,6 +21,12 @@ variable "proxmox_tls_insecure" {
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "proxmox_host" {
|
||||
description = "Proxmox host for SSH access (used to upload cloud-init snippets)"
|
||||
type = string
|
||||
default = "pve1.home.2rjus.net"
|
||||
}
|
||||
|
||||
# Default values for VM configurations
|
||||
# These can be overridden per-VM in vms.tf
|
||||
|
||||
|
||||
@@ -22,6 +22,12 @@ locals {
|
||||
# disk_size = "50G"
|
||||
# }
|
||||
|
||||
# Example Test VM with custom git branch (for testing pipeline changes):
|
||||
# "test-vm" = {
|
||||
# ip = "10.69.13.100/24"
|
||||
# flake_branch = "test-pipeline" # Bootstrap from this branch instead of master
|
||||
# }
|
||||
|
||||
# Example Minimal VM using all defaults (uncomment to deploy):
|
||||
# "minimal-vm" = {}
|
||||
# "bootstrap-verify-test" = {}
|
||||
@@ -44,6 +50,8 @@ locals {
|
||||
# Network configuration - detect DHCP vs static
|
||||
ip = lookup(vm, "ip", null)
|
||||
gateway = lookup(vm, "gateway", var.default_gateway)
|
||||
# Branch configuration for bootstrap (optional, uses master if not set)
|
||||
flake_branch = lookup(vm, "flake_branch", null)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,6 +119,9 @@ resource "proxmox_vm_qemu" "vm" {
|
||||
# Network configuration - DHCP or static IP
|
||||
ipconfig0 = each.value.ip != null ? "ip=${each.value.ip},gw=${each.value.gateway}" : "ip=dhcp"
|
||||
|
||||
# Custom cloud-init disk for branch configuration (if flake_branch is set)
|
||||
cicustom = each.value.flake_branch != null ? "user=${each.value.storage}:snippets/cloud-init-${each.key}.yml" : null
|
||||
|
||||
# Skip IPv6 since we don't use it
|
||||
skip_ipv6 = true
|
||||
|
||||
|
||||
Reference in New Issue
Block a user