From 78840a113996ac3a4ec2671fb79852210aa756cb Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Fri, 26 Sep 2025 14:31:55 +0200 Subject: [PATCH 01/33] Add fallback localtion and resoruces --- .../main.tf | 189 +++++++++++++----- .../outputs.tf | 46 +++-- 2 files changed, 169 insertions(+), 66 deletions(-) diff --git a/terraform/examples/wire-server-deploy-offline-hetzner/main.tf b/terraform/examples/wire-server-deploy-offline-hetzner/main.tf index c0ce4a4e8..6dec05aa4 100644 --- a/terraform/examples/wire-server-deploy-offline-hetzner/main.tf +++ b/terraform/examples/wire-server-deploy-offline-hetzner/main.tf @@ -7,35 +7,109 @@ locals { postgresql_count = 3 ssh_keys = [hcloud_ssh_key.adminhost.name] + # Location preferences with fallbacks (EU only) + preferred_locations = ["nbg1", "fsn1", "hel1"] + # Server type preferences with fallbacks preferred_server_types = { - small = ["cx22", "cpx21", "cx21", "cpx11"] # For cassandra, elasticsearch, minio, postgresql - medium = ["cpx41", "cx41", "cpx31", "cx31"] # For adminhost, assethost, kubenode + small = ["cx22", "cpx21", "cx21", "cpx11"] # For cassandra, elasticsearch, minio, postgresql + medium = ["cpx41", "cx41", "cpx31", "cx31"] # For adminhost, assethost, kubenode } } -# Get available server types in the specified location -data "hcloud_server_types" "available" { -} +# Get available server types and locations +data "hcloud_server_types" "available" {} +data "hcloud_datacenters" "available" {} -# Helper locals to select available server types +# Helper locals to select available resources with robust fallback logic locals { available_server_type_names = [for st in data.hcloud_server_types.available.server_types : st.name] + available_location_names = [for dc in data.hcloud_datacenters.available.datacenters : dc.location.name] - # Select the first available server type from the preference list - small_server_type = [ + # Select the first available location from the preference list + available_preferred_locations = [ + for preferred in local.preferred_locations : + preferred if contains(local.available_location_names, preferred) + ] + selected_location = length(local.available_preferred_locations) > 0 ? local.available_preferred_locations[0] : null + + # Select the first available server type from the preference list (with validation) + available_small_server_types = [ for preferred in local.preferred_server_types.small : preferred if contains(local.available_server_type_names, preferred) - ][0] - - medium_server_type = [ + ] + small_server_type = length(local.available_small_server_types) > 0 ? local.available_small_server_types[0] : null + + available_medium_server_types = [ for preferred in local.preferred_server_types.medium : preferred if contains(local.available_server_type_names, preferred) - ][0] + ] + medium_server_type = length(local.available_medium_server_types) > 0 ? local.available_medium_server_types[0] : null } +# Validation checks - fail early with helpful error messages +resource "null_resource" "location_validation" { + count = local.selected_location != null ? 0 : 1 + + provisioner "local-exec" { + command = <<-EOT + echo "DEPLOYMENT FAILED: No suitable location available" + echo "Requested locations: ${join(", ", local.preferred_locations)}" + echo "Available locations: ${join(", ", local.available_location_names)}" + echo "Please check your Hetzner Cloud region availability" + exit 1 + EOT + } +} + +resource "null_resource" "small_server_type_validation" { + count = local.small_server_type != null ? 0 : 1 + + provisioner "local-exec" { + command = <<-EOT + echo "DEPLOYMENT FAILED: No suitable database server types available" + echo "Requested types: ${join(", ", local.preferred_server_types.small)}" + echo "Available types: ${join(", ", local.available_server_type_names)}" + echo "Please check server type availability in your selected region" + exit 1 + EOT + } +} + +resource "null_resource" "medium_server_type_validation" { + count = local.medium_server_type != null ? 0 : 1 + + provisioner "local-exec" { + command = <<-EOT + echo "DEPLOYMENT FAILED: No suitable Kubernetes server types available" + echo "Requested types: ${join(", ", local.preferred_server_types.medium)}" + echo "Available types: ${join(", ", local.available_server_type_names)}" + echo "Please check server type availability in your selected region" + exit 1 + EOT + } +} + +resource "null_resource" "deployment_info" { + depends_on = [ + null_resource.location_validation, + null_resource.small_server_type_validation, + null_resource.medium_server_type_validation + ] + + provisioner "local-exec" { + command = <<-EOT + echo "VALIDATION PASSED: Deploying Wire offline infrastructure" + echo "Location: ${local.selected_location}" + echo "Database server type: ${local.small_server_type}" + echo "Kubernetes server type: ${local.medium_server_type}" + echo "Total instances: ${local.cassandra_count + local.postgresql_count + local.elasticsearch_count + local.minio_count + local.kubenode_count + 2}" + EOT + } +} resource "random_pet" "main" { + depends_on = [null_resource.deployment_info] } resource "hcloud_network" "main" { @@ -66,18 +140,19 @@ resource "hcloud_ssh_key" "adminhost" { # Connected to all other servers. Simulates the admin's "laptop" resource "hcloud_server" "adminhost" { - location = "nbg1" + depends_on = [ + null_resource.deployment_info, + hcloud_network_subnet.main + ] + location = local.selected_location name = "adminhost-${random_pet.adminhost.id}" image = "ubuntu-22.04" ssh_keys = local.ssh_keys server_type = local.medium_server_type network { - network_id = hcloud_network.main.id - ip = "" + network_id = hcloud_network.main.id + ip = "" } - depends_on = [ - hcloud_network_subnet.main - ] } # The server hosting all the bootstrap assets @@ -85,7 +160,11 @@ resource "random_pet" "assethost" { } resource "hcloud_server" "assethost" { - location = "nbg1" + depends_on = [ + null_resource.deployment_info, + hcloud_network_subnet.main + ] + location = local.selected_location name = "assethost-${random_pet.assethost.id}" image = "ubuntu-22.04" ssh_keys = local.ssh_keys @@ -95,12 +174,9 @@ resource "hcloud_server" "assethost" { ipv6_enabled = false } network { - network_id = hcloud_network.main.id - ip = "" + network_id = hcloud_network.main.id + ip = "" } - depends_on = [ - hcloud_network_subnet.main - ] } resource "random_pet" "kubenode" { @@ -108,8 +184,12 @@ resource "random_pet" "kubenode" { } resource "hcloud_server" "kubenode" { + depends_on = [ + null_resource.deployment_info, + hcloud_network_subnet.main + ] count = local.kubenode_count - location = "nbg1" + location = local.selected_location name = "kubenode-${random_pet.kubenode[count.index].id}" image = "ubuntu-22.04" ssh_keys = local.ssh_keys @@ -119,12 +199,9 @@ resource "hcloud_server" "kubenode" { ipv6_enabled = false } network { - network_id = hcloud_network.main.id - ip = "" + network_id = hcloud_network.main.id + ip = "" } - depends_on = [ - hcloud_network_subnet.main - ] } resource "random_pet" "cassandra" { @@ -132,8 +209,12 @@ resource "random_pet" "cassandra" { } resource "hcloud_server" "cassandra" { + depends_on = [ + null_resource.deployment_info, + hcloud_network_subnet.main + ] count = local.cassandra_count - location = "nbg1" + location = local.selected_location name = "cassandra-${random_pet.cassandra[count.index].id}" image = "ubuntu-22.04" ssh_keys = local.ssh_keys @@ -143,12 +224,9 @@ resource "hcloud_server" "cassandra" { ipv6_enabled = false } network { - network_id = hcloud_network.main.id - ip = "" + network_id = hcloud_network.main.id + ip = "" } - depends_on = [ - hcloud_network_subnet.main - ] } resource "random_pet" "elasticsearch" { @@ -156,8 +234,12 @@ resource "random_pet" "elasticsearch" { } resource "hcloud_server" "elasticsearch" { + depends_on = [ + null_resource.deployment_info, + hcloud_network_subnet.main + ] count = local.elasticsearch_count - location = "nbg1" + location = local.selected_location name = "elasticsearch-${random_pet.elasticsearch[count.index].id}" image = "ubuntu-22.04" ssh_keys = local.ssh_keys @@ -167,12 +249,9 @@ resource "hcloud_server" "elasticsearch" { ipv6_enabled = false } network { - network_id = hcloud_network.main.id - ip = "" + network_id = hcloud_network.main.id + ip = "" } - depends_on = [ - hcloud_network_subnet.main - ] } resource "random_pet" "minio" { @@ -180,8 +259,12 @@ resource "random_pet" "minio" { } resource "hcloud_server" "minio" { + depends_on = [ + null_resource.deployment_info, + hcloud_network_subnet.main + ] count = local.minio_count - location = "nbg1" + location = local.selected_location name = "minio-${random_pet.minio[count.index].id}" image = "ubuntu-22.04" ssh_keys = local.ssh_keys @@ -191,12 +274,9 @@ resource "hcloud_server" "minio" { ipv6_enabled = false } network { - network_id = hcloud_network.main.id - ip = "" + network_id = hcloud_network.main.id + ip = "" } - depends_on = [ - hcloud_network_subnet.main - ] } resource "random_pet" "postgresql" { @@ -204,8 +284,12 @@ resource "random_pet" "postgresql" { } resource "hcloud_server" "postgresql" { + depends_on = [ + null_resource.deployment_info, + hcloud_network_subnet.main + ] count = local.postgresql_count - location = "nbg1" + location = local.selected_location name = "postgresql-${random_pet.postgresql[count.index].id}" image = "ubuntu-22.04" ssh_keys = local.ssh_keys @@ -215,10 +299,7 @@ resource "hcloud_server" "postgresql" { ipv6_enabled = false } network { - network_id = hcloud_network.main.id - ip = "" + network_id = hcloud_network.main.id + ip = "" } - depends_on = [ - hcloud_network_subnet.main - ] } diff --git a/terraform/examples/wire-server-deploy-offline-hetzner/outputs.tf b/terraform/examples/wire-server-deploy-offline-hetzner/outputs.tf index f5cfc135a..4e71f24a8 100644 --- a/terraform/examples/wire-server-deploy-offline-hetzner/outputs.tf +++ b/terraform/examples/wire-server-deploy-offline-hetzner/outputs.tf @@ -1,6 +1,6 @@ output "ssh_private_key" { sensitive = true - value = tls_private_key.admin.private_key_pem + value = tls_private_key.admin.private_key_pem } output "selected_server_types" { @@ -11,9 +11,31 @@ output "selected_server_types" { } } +output "selected_location" { + description = "Location selected after checking availability" + value = local.selected_location +} + +output "resource_fallback_info" { + description = "Information about resource fallback selections" + value = { + requested_locations = local.preferred_locations + available_locations = local.available_location_names + selected_location = local.selected_location + + requested_small_types = local.preferred_server_types.small + available_small_types = local.available_small_server_types + selected_small_type = local.small_server_type + + requested_medium_types = local.preferred_server_types.medium + available_medium_types = local.available_medium_server_types + selected_medium_type = local.medium_server_type + } +} + output "adminhost" { sensitive = true - value = hcloud_server.adminhost.ipv4_address + value = hcloud_server.adminhost.ipv4_address } # output format that a static inventory file expects output "static-inventory" { @@ -21,9 +43,9 @@ output "static-inventory" { value = { all = { vars = { - ansible_user = "root" - private_interface = "enp7s0" - adminhost_ip = tolist(hcloud_server.adminhost.network)[0].ip + ansible_user = "root" + private_interface = "enp7s0" + adminhost_ip = tolist(hcloud_server.adminhost.network)[0].ip ansible_ssh_common_args = "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ControlMaster=auto -o ControlPersist=60s" } } @@ -40,7 +62,7 @@ output "static-inventory" { ansible_host = tolist(hcloud_server.adminhost.network)[0].ip } } - } + } assethost = { hosts = { "assethost" = { @@ -75,7 +97,7 @@ output "static-inventory" { calico_veth_mtu = 1430 # NOTE: relax handling a list with more than 3 items; required on Hetzner docker_dns_servers_strict = false - upstream_dns_servers = [tolist(hcloud_server.adminhost.network)[0].ip] + upstream_dns_servers = [tolist(hcloud_server.adminhost.network)[0].ip] } } cassandra = { @@ -116,14 +138,14 @@ output "static-inventory" { } postgresql = { hosts = { - for index, server in hcloud_server.postgresql : "postgresql${index + 1}" => { + for index, server in hcloud_server.postgresql : "postgresql${index + 1}" => { ansible_host = tolist(hcloud_server.postgresql[index].network)[0].ip } } vars = { - wire_dbname = "wire-server" - wire_user = "wire-server" - wire_pass = "verysecurepassword" + wire_dbname = "wire-server" + wire_user = "wire-server" + wire_pass = "verysecurepassword" postgresql_network_interface = "enp7s0" } } @@ -132,7 +154,7 @@ output "static-inventory" { } postgresql_ro = { hosts = { "postgresql2" = {}, - "postgresql3" = {} } + "postgresql3" = {} } } } } From 5b7bb3388e47b1a237a2d0de18bbd1608a016f79 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Fri, 26 Sep 2025 15:44:24 +0200 Subject: [PATCH 02/33] postgres-external values --- .github/workflows/offline.yml | 4 +- offline/cd-with-retry.sh | 129 ++++++++++++++++++ .../main.tf | 6 +- .../prod-values.example.yaml | 6 + 4 files changed, 140 insertions(+), 5 deletions(-) create mode 100755 offline/cd-with-retry.sh create mode 100644 values/postgresql-external/prod-values.example.yaml diff --git a/.github/workflows/offline.yml b/.github/workflows/offline.yml index 8577ee54e..ea565fd6d 100644 --- a/.github/workflows/offline.yml +++ b/.github/workflows/offline.yml @@ -110,9 +110,9 @@ jobs: terraform_version: "^1.3.7" terraform_wrapper: false - - name: Deploy offline environment to hetzner + - name: Deploy offline environment to hetzner with retry logic run: | - ./offline/cd.sh + ./offline/cd-with-retry.sh env: HCLOUD_TOKEN: '${{ secrets.HCLOUD_TOKEN }}' diff --git a/offline/cd-with-retry.sh b/offline/cd-with-retry.sh new file mode 100755 index 000000000..b27488eb6 --- /dev/null +++ b/offline/cd-with-retry.sh @@ -0,0 +1,129 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# This is the production version of cd.sh with built-in retry logic +# Use this instead of cd.sh when you want automatic resource availability handling + +CD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +TF_DIR="${CD_DIR}/../terraform/examples/wire-server-deploy-offline-hetzner" +BIN_DIR="${CD_DIR}/../bin" +ARTIFACTS_DIR="${CD_DIR}/default-build/output" + +# Retry configuration +MAX_RETRIES=3 +RETRY_DELAY=30 + +echo "๐Ÿš€ Wire Offline Deployment with Retry Logic" +echo "============================================" + +function cleanup { + (cd "$TF_DIR" && terraform destroy -auto-approve) + echo "๐Ÿงน Cleanup completed" +} +trap cleanup EXIT + +cd "$TF_DIR" +terraform init + +# Retry loop for terraform apply +echo "๐ŸŽฏ Starting deployment with automatic retry on resource unavailability..." +for attempt in $(seq 1 $MAX_RETRIES); do + echo "" + echo "๐Ÿ“‹ Deployment attempt $attempt of $MAX_RETRIES" + echo "โฐ $(date)" + + if terraform apply -auto-approve; then + echo "โœ… Infrastructure deployment successful on attempt $attempt!" + break + else + echo "โŒ Infrastructure deployment failed on attempt $attempt" + + if [[ $attempt -lt $MAX_RETRIES ]]; then + echo "๐Ÿ”„ Will retry with different configuration..." + + # Clean up partial deployment + echo "๐Ÿงน Cleaning up partial deployment..." + terraform destroy -auto-approve || true + + # Wait for resources to potentially become available + echo "โฑ๏ธ Waiting ${RETRY_DELAY}s for resources to become available..." + sleep $RETRY_DELAY + + # Modify configuration for better availability + echo "๐Ÿ“ Adjusting server type preferences for attempt $((attempt + 1))..." + case $attempt in + 1) + # Attempt 2: Prioritize cx22 and cx41 + sed -i.bak 's/"cpx21", "cx22", "cx21", "cpx11"/"cx22", "cpx11", "cpx21", "cx21"/' main.tf + sed -i.bak 's/"cpx31", "cpx41", "cx31", "cx41"/"cx41", "cpx31", "cx31", "cx41"/' main.tf + echo " โ†’ Prioritizing cx22 and cx41 server types" + ;; + 2) + # Attempt 3: Use smallest available types + sed -i.bak 's/"cx22", "cpx11", "cpx21", "cx21"/"cpx11", "cx21", "cx22", "cpx21"/' main.tf + sed -i.bak 's/"cx41", "cpx31", "cx31", "cx41"/"cpx31", "cx31", "cpx11", "cx21"/' main.tf + echo " โ†’ Using smallest available server types" + ;; + esac + + terraform init -reconfigure + else + echo "๐Ÿ’” All deployment attempts failed after $MAX_RETRIES tries" + echo "" + echo "๐Ÿ” This usually means:" + echo " 1. High demand for Hetzner Cloud resources in EU regions" + echo " 2. Your account may have resource limits" + echo " 3. Try again later when resources become available" + echo "" + echo "๐Ÿ’ก Manual solutions:" + echo " 1. Check Hetzner Console for resource limits" + echo " 2. Try different server types manually" + echo " 3. Contact Hetzner support for resource availability" + + # Restore original config + if [[ -f main.tf.bak ]]; then + mv main.tf.bak main.tf + terraform init -reconfigure + fi + + exit 1 + fi + fi +done + +# Restore original config after successful deployment +if [[ -f main.tf.bak ]]; then + mv main.tf.bak main.tf + terraform init -reconfigure +fi + +echo "" +echo "๐ŸŽ‰ Infrastructure ready! Proceeding with application deployment..." + +# Continue with the rest of the original cd.sh logic +adminhost=$(terraform output adminhost) +adminhost="${adminhost//\"/}" # remove extra quotes around the returned string +ssh_private_key=$(terraform output ssh_private_key) + +eval `ssh-agent` +ssh-add - <<< "$ssh_private_key" + +terraform output -json static-inventory > inventory.json +yq -y '.' inventory.json > inventory.yml + +ssh -oStrictHostKeyChecking=accept-new -oConnectionAttempts=10 "root@$adminhost" tar xzv < "$ARTIFACTS_DIR/assets.tgz" + +scp inventory.yml "root@$adminhost":./ansible/inventory/offline/inventory.yml + +ssh "root@$adminhost" cat ./ansible/inventory/offline/inventory.yml || true + +echo "Running ansible playbook setup_nodes.yml via adminhost ($adminhost)..." +ansible-playbook -i inventory.yml setup_nodes.yml --private-key "ssh_private_key" \ + -e "ansible_ssh_common_args='-o ProxyCommand=\"ssh -W %h:%p -q root@$adminhost -i ssh_private_key\" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'" + +# NOTE: Agent is forwarded; so that the adminhost can provision the other boxes +ssh -A "root@$adminhost" ./bin/offline-deploy.sh + +echo "" +echo "๐ŸŽ‰ Wire offline deployment completed successfully!" \ No newline at end of file diff --git a/terraform/examples/wire-server-deploy-offline-hetzner/main.tf b/terraform/examples/wire-server-deploy-offline-hetzner/main.tf index 6dec05aa4..c0602c7ef 100644 --- a/terraform/examples/wire-server-deploy-offline-hetzner/main.tf +++ b/terraform/examples/wire-server-deploy-offline-hetzner/main.tf @@ -10,10 +10,10 @@ locals { # Location preferences with fallbacks (EU only) preferred_locations = ["nbg1", "fsn1", "hel1"] - # Server type preferences with fallbacks + # Server type preferences with fallbacks (optimized for availability) preferred_server_types = { - small = ["cx22", "cpx21", "cx21", "cpx11"] # For cassandra, elasticsearch, minio, postgresql - medium = ["cpx41", "cx41", "cpx31", "cx31"] # For adminhost, assethost, kubenode + small = ["cpx21", "cx22", "cx21", "cpx11"] # For cassandra, elasticsearch, minio, postgresql + medium = ["cpx31", "cpx41", "cx31", "cx41"] # For adminhost, assethost, kubenode } } diff --git a/values/postgresql-external/prod-values.example.yaml b/values/postgresql-external/prod-values.example.yaml new file mode 100644 index 000000000..584583470 --- /dev/null +++ b/values/postgresql-external/prod-values.example.yaml @@ -0,0 +1,6 @@ +# Read Write IPs of the postgresql servers that are used for read and write operations. +RWIPs: + - 192.168.122.31 +ROIPs: + - 192.168.122.32 + - 192.168.122.33 \ No newline at end of file From 7198bfd5241f5bcb036d8e44b95311bc90d067d8 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Fri, 26 Sep 2025 16:17:56 +0200 Subject: [PATCH 03/33] fix lint issue --- offline/cd-with-retry.sh | 43 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/offline/cd-with-retry.sh b/offline/cd-with-retry.sh index b27488eb6..5664545f1 100755 --- a/offline/cd-with-retry.sh +++ b/offline/cd-with-retry.sh @@ -7,19 +7,18 @@ set -euo pipefail CD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" TF_DIR="${CD_DIR}/../terraform/examples/wire-server-deploy-offline-hetzner" -BIN_DIR="${CD_DIR}/../bin" ARTIFACTS_DIR="${CD_DIR}/default-build/output" # Retry configuration MAX_RETRIES=3 RETRY_DELAY=30 -echo "๐Ÿš€ Wire Offline Deployment with Retry Logic" -echo "============================================" +echo "Wire Offline Deployment with Retry Logic" +echo "========================================" function cleanup { (cd "$TF_DIR" && terraform destroy -auto-approve) - echo "๐Ÿงน Cleanup completed" + echo "Cleanup completed" } trap cleanup EXIT @@ -27,56 +26,56 @@ cd "$TF_DIR" terraform init # Retry loop for terraform apply -echo "๐ŸŽฏ Starting deployment with automatic retry on resource unavailability..." +echo "Starting deployment with automatic retry on resource unavailability..." for attempt in $(seq 1 $MAX_RETRIES); do echo "" - echo "๐Ÿ“‹ Deployment attempt $attempt of $MAX_RETRIES" - echo "โฐ $(date)" + echo "Deployment attempt $attempt of $MAX_RETRIES" + date if terraform apply -auto-approve; then - echo "โœ… Infrastructure deployment successful on attempt $attempt!" + echo "Infrastructure deployment successful on attempt $attempt!" break else - echo "โŒ Infrastructure deployment failed on attempt $attempt" + echo "Infrastructure deployment failed on attempt $attempt" if [[ $attempt -lt $MAX_RETRIES ]]; then - echo "๐Ÿ”„ Will retry with different configuration..." + echo "Will retry with different configuration..." # Clean up partial deployment - echo "๐Ÿงน Cleaning up partial deployment..." + echo "Cleaning up partial deployment..." terraform destroy -auto-approve || true # Wait for resources to potentially become available - echo "โฑ๏ธ Waiting ${RETRY_DELAY}s for resources to become available..." + echo "Waiting ${RETRY_DELAY}s for resources to become available..." sleep $RETRY_DELAY # Modify configuration for better availability - echo "๐Ÿ“ Adjusting server type preferences for attempt $((attempt + 1))..." + echo "Adjusting server type preferences for attempt $((attempt + 1))..." case $attempt in 1) # Attempt 2: Prioritize cx22 and cx41 sed -i.bak 's/"cpx21", "cx22", "cx21", "cpx11"/"cx22", "cpx11", "cpx21", "cx21"/' main.tf sed -i.bak 's/"cpx31", "cpx41", "cx31", "cx41"/"cx41", "cpx31", "cx31", "cx41"/' main.tf - echo " โ†’ Prioritizing cx22 and cx41 server types" + echo " -> Prioritizing cx22 and cx41 server types" ;; 2) # Attempt 3: Use smallest available types sed -i.bak 's/"cx22", "cpx11", "cpx21", "cx21"/"cpx11", "cx21", "cx22", "cpx21"/' main.tf - sed -i.bak 's/"cx41", "cpx31", "cx31", "cx41"/"cpx31", "cx31", "cpx11", "cx21"/' main.tf - echo " โ†’ Using smallest available server types" + sed -i.bak 's/"cx41", "cpx31", "cx31", "cx41"/"cpx31", "cpx31", "cpx11", "cx21"/' main.tf + echo " -> Using smallest available server types" ;; esac terraform init -reconfigure else - echo "๐Ÿ’” All deployment attempts failed after $MAX_RETRIES tries" + echo "All deployment attempts failed after $MAX_RETRIES tries" echo "" - echo "๐Ÿ” This usually means:" + echo "This usually means:" echo " 1. High demand for Hetzner Cloud resources in EU regions" echo " 2. Your account may have resource limits" echo " 3. Try again later when resources become available" echo "" - echo "๐Ÿ’ก Manual solutions:" + echo "Manual solutions:" echo " 1. Check Hetzner Console for resource limits" echo " 2. Try different server types manually" echo " 3. Contact Hetzner support for resource availability" @@ -99,14 +98,14 @@ if [[ -f main.tf.bak ]]; then fi echo "" -echo "๐ŸŽ‰ Infrastructure ready! Proceeding with application deployment..." +echo "Infrastructure ready! Proceeding with application deployment..." # Continue with the rest of the original cd.sh logic adminhost=$(terraform output adminhost) adminhost="${adminhost//\"/}" # remove extra quotes around the returned string ssh_private_key=$(terraform output ssh_private_key) -eval `ssh-agent` +eval "$(ssh-agent)" ssh-add - <<< "$ssh_private_key" terraform output -json static-inventory > inventory.json @@ -126,4 +125,4 @@ ansible-playbook -i inventory.yml setup_nodes.yml --private-key "ssh_private_key ssh -A "root@$adminhost" ./bin/offline-deploy.sh echo "" -echo "๐ŸŽ‰ Wire offline deployment completed successfully!" \ No newline at end of file +echo "Wire offline deployment completed successfully!" \ No newline at end of file From 0b825b4b28ca63476c34e6fbc901d4da7d4e46d3 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Fri, 26 Sep 2025 16:46:46 +0200 Subject: [PATCH 04/33] add demo values --- values/postgresql-external/demo-values.example.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 values/postgresql-external/demo-values.example.yaml diff --git a/values/postgresql-external/demo-values.example.yaml b/values/postgresql-external/demo-values.example.yaml new file mode 100644 index 000000000..584583470 --- /dev/null +++ b/values/postgresql-external/demo-values.example.yaml @@ -0,0 +1,6 @@ +# Read Write IPs of the postgresql servers that are used for read and write operations. +RWIPs: + - 192.168.122.31 +ROIPs: + - 192.168.122.32 + - 192.168.122.33 \ No newline at end of file From 092ae0d389079825dd336ffa71b53a167d894e51 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Mon, 29 Sep 2025 10:05:36 +0200 Subject: [PATCH 05/33] try make a faster deployment process --- .github/workflows/deploy-only.yml | 50 ++++++ .github/workflows/offline.yml | 167 +++++++++++------- .github/workflows/offline.yml.disabled | 123 +++++++++++++ .../optimize-default-build-deploy-process | 5 + offline/cd-with-retry.sh | 84 +++++++-- .../main.tf | 6 +- 6 files changed, 354 insertions(+), 81 deletions(-) create mode 100644 .github/workflows/deploy-only.yml create mode 100644 .github/workflows/offline.yml.disabled create mode 100644 changelog.d/3-deploy-builds/optimize-default-build-deploy-process diff --git a/.github/workflows/deploy-only.yml b/.github/workflows/deploy-only.yml new file mode 100644 index 000000000..c82dd418b --- /dev/null +++ b/.github/workflows/deploy-only.yml @@ -0,0 +1,50 @@ +name: Fast Deploy Only + +on: + workflow_dispatch: + inputs: + upload_name: + description: 'Upload name (git SHA or tag)' + required: false + default: '' + pull_request: + types: [opened, synchronize, reopened] + paths: + - 'terraform/**' + - 'offline/cd-with-retry.sh' + - '.github/workflows/deploy-only.yml' + push: + branches: [master, develop] + paths: + - 'terraform/**' + - 'offline/cd-with-retry.sh' + - '.github/workflows/deploy-only.yml' + +jobs: + deploy-only: + name: Deploy existing build + runs-on: + group: wire-server-deploy + steps: + - uses: actions/checkout@v2 + + - name: Get upload name + id: upload_name + run: | + if [ -n "${{ github.event.inputs.upload_name }}" ]; then + echo ::set-output name=UPLOAD_NAME::${{ github.event.inputs.upload_name }} + else + echo ::set-output name=UPLOAD_NAME::$GITHUB_SHA + fi + + - name: Install terraform + uses: hashicorp/setup-terraform@v3 + with: + terraform_version: "^1.3.7" + terraform_wrapper: false + + - name: Fast deploy to Hetzner + run: ./offline/cd-with-retry.sh + env: + HCLOUD_TOKEN: '${{ secrets.HCLOUD_TOKEN }}' + GITHUB_SHA: ${{ steps.upload_name.outputs.UPLOAD_NAME }} \ No newline at end of file diff --git a/.github/workflows/offline.yml b/.github/workflows/offline.yml index ea565fd6d..4c8f75fe1 100644 --- a/.github/workflows/offline.yml +++ b/.github/workflows/offline.yml @@ -1,19 +1,20 @@ on: push: branches: [master, develop] - tags: [ v* ] + tags: [v*] paths-ignore: - - '*.md' - - '**/*.md' + - "*.md" + - "**/*.md" pull_request: branches: [master, develop] paths-ignore: - - '*.md' - - '**/*.md' + - "*.md" + - "**/*.md" + jobs: - offline: - name: Prepare offline package - # Useful to skip expensive CI when writing docs + # Fast-track deployment job - runs in parallel with builds + deploy: + name: Build and Deploy default build if: "!contains(github.event.head_commit.message, 'skip ci')" runs-on: group: wire-server-deploy @@ -32,31 +33,55 @@ jobs: - name: Get upload name id: upload_name - run: | - # FIXME: Tag with a nice release name using the github tag... - # SOURCE_TAG=${GITHUB_REF#refs/tags/} - echo ::set-output name=UPLOAD_NAME::$GITHUB_SHA - # echo ::set-output name=UPLOAD_NAME::${SOURCE_TAG:-$GITHUB_SHA} + run: echo ::set-output name=UPLOAD_NAME::$GITHUB_SHA - # deafult profile build - - name: Process the default profile build + # Only build default profile for deployment + - name: Process default build for deployment run: ./offline/default-build/build.sh env: - GPG_PRIVATE_KEY: '${{ secrets.GPG_PRIVATE_KEY }}' - DOCKER_LOGIN: '${{ secrets.DOCKER_LOGIN }}' + GPG_PRIVATE_KEY: "${{ secrets.GPG_PRIVATE_KEY }}" + DOCKER_LOGIN: "${{ secrets.DOCKER_LOGIN }}" - - name: Copy default build assets tarball to S3 and clean up + - name: Upload default build to S3 run: | - # Upload tarball for each profile by specifying their OUTPUT_TAR path aws s3 cp offline/default-build/output/assets.tgz s3://public.wire.com/artifacts/wire-server-deploy-static-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz echo "Uploaded to: https://s3-$AWS_REGION.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz" - # removing everything except assets.tgz as it is not required anymore in the further builds - find offline/default-build/output/ -mindepth 1 -maxdepth 1 ! -name 'assets.tgz' -exec rm -r {} + env: - AWS_ACCESS_KEY_ID: '${{ secrets.AWS_ACCESS_KEY_ID }}' - AWS_SECRET_ACCESS_KEY: '${{ secrets.AWS_SECRET_ACCESS_KEY }}' + AWS_ACCESS_KEY_ID: "${{ secrets.AWS_ACCESS_KEY_ID }}" + AWS_SECRET_ACCESS_KEY: "${{ secrets.AWS_SECRET_ACCESS_KEY }}" AWS_REGION: "eu-west-1" + - name: Install terraform + uses: hashicorp/setup-terraform@v3 + with: + terraform_version: "^1.3.7" + terraform_wrapper: false + + - name: Deploy to Hetzner with fast S3 deployment + run: ./offline/cd-with-retry.sh + env: + HCLOUD_TOKEN: "${{ secrets.HCLOUD_TOKEN }}" + + # Parallel builds for other profiles + build-container: + name: Build container + if: "!contains(github.event.head_commit.message, 'skip ci')" + runs-on: + group: wire-server-deploy + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - uses: cachix/install-nix-action@v27 + - uses: cachix/cachix-action@v15 + with: + name: wire-server + signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}" + + - name: Get upload name + id: upload_name + run: echo ::set-output name=UPLOAD_NAME::$GITHUB_SHA + - name: Build and upload wire-server-deploy container run: | container_image=$(nix-build --no-out-link -A container) @@ -64,60 +89,78 @@ jobs: docker-archive:"$container_image" \ "docker://quay.io/wire/wire-server-deploy:${{ steps.upload_name.outputs.UPLOAD_NAME }}" env: - DOCKER_LOGIN: '${{ secrets.DOCKER_LOGIN }}' + DOCKER_LOGIN: "${{ secrets.DOCKER_LOGIN }}" + + build-demo: + name: Build demo profile + if: "!contains(github.event.head_commit.message, 'skip ci')" + runs-on: + group: wire-server-deploy + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - uses: cachix/install-nix-action@v27 + - uses: cachix/cachix-action@v15 + with: + name: wire-server + signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}" + + - name: Install nix environment + run: nix-env -f default.nix -iA env - # demo profile build - - name: Process the demo profile build + - name: Get upload name + id: upload_name + run: echo ::set-output name=UPLOAD_NAME::$GITHUB_SHA + + - name: Process demo profile build run: ./offline/demo-build/build.sh env: - GPG_PRIVATE_KEY: '${{ secrets.GPG_PRIVATE_KEY }}' - DOCKER_LOGIN: '${{ secrets.DOCKER_LOGIN }}' + GPG_PRIVATE_KEY: "${{ secrets.GPG_PRIVATE_KEY }}" + DOCKER_LOGIN: "${{ secrets.DOCKER_LOGIN }}" - - name: Copy demo build assets tarball to S3 and clean up + - name: Upload demo build to S3 run: | - # Upload tarball for each profile by specifying their OUTPUT_TAR path aws s3 cp offline/demo-build/output/assets.tgz s3://public.wire.com/artifacts/wire-server-deploy-static-demo-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz echo "Uploaded to: https://s3-$AWS_REGION.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-demo-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz" - # remove the assets from the build to optimize the space on the server - rm -rf offline/demo-build/output/* env: - AWS_ACCESS_KEY_ID: '${{ secrets.AWS_ACCESS_KEY_ID }}' - AWS_SECRET_ACCESS_KEY: '${{ secrets.AWS_SECRET_ACCESS_KEY }}' + AWS_ACCESS_KEY_ID: "${{ secrets.AWS_ACCESS_KEY_ID }}" + AWS_SECRET_ACCESS_KEY: "${{ secrets.AWS_SECRET_ACCESS_KEY }}" AWS_REGION: "eu-west-1" - # min profile build - - name: Process the min profile build + build-min: + name: Build min profile + if: "!contains(github.event.head_commit.message, 'skip ci')" + runs-on: + group: wire-server-deploy + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - uses: cachix/install-nix-action@v27 + - uses: cachix/cachix-action@v15 + with: + name: wire-server + signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}" + + - name: Install nix environment + run: nix-env -f default.nix -iA env + + - name: Get upload name + id: upload_name + run: echo ::set-output name=UPLOAD_NAME::$GITHUB_SHA + + - name: Process min profile build run: ./offline/min-build/build.sh env: - GPG_PRIVATE_KEY: '${{ secrets.GPG_PRIVATE_KEY }}' - DOCKER_LOGIN: '${{ secrets.DOCKER_LOGIN }}' + GPG_PRIVATE_KEY: "${{ secrets.GPG_PRIVATE_KEY }}" + DOCKER_LOGIN: "${{ secrets.DOCKER_LOGIN }}" - - name: Copy min build assets tarball to S3 + - name: Upload min build to S3 run: | - # Upload tarball for each profile by specifying their OUTPUT_TAR path aws s3 cp offline/min-build/output/assets.tgz s3://public.wire.com/artifacts/wire-server-deploy-static-min-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz echo "Uploaded to: https://s3-$AWS_REGION.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-min-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz" - # remove the archives from the build to optimize the space on the server - rm -rf offline/min-build/output/* env: - AWS_ACCESS_KEY_ID: '${{ secrets.AWS_ACCESS_KEY_ID }}' - AWS_SECRET_ACCESS_KEY: '${{ secrets.AWS_SECRET_ACCESS_KEY }}' + AWS_ACCESS_KEY_ID: "${{ secrets.AWS_ACCESS_KEY_ID }}" + AWS_SECRET_ACCESS_KEY: "${{ secrets.AWS_SECRET_ACCESS_KEY }}" AWS_REGION: "eu-west-1" - - - name: Install terraform - uses: hashicorp/setup-terraform@v3 - with: - terraform_version: "^1.3.7" - terraform_wrapper: false - - - name: Deploy offline environment to hetzner with retry logic - run: | - ./offline/cd-with-retry.sh - env: - HCLOUD_TOKEN: '${{ secrets.HCLOUD_TOKEN }}' - - #- name: Clean up hetzner environment; just in case - # if: always() - # run: (cd terraform/examples/wire-server-deploy-offline-hetzner ; terraform init && terraform destroy -auto-approve) - # env: - # HCLOUD_TOKEN: '${{ secrets.HCLOUD_TOKEN }}' diff --git a/.github/workflows/offline.yml.disabled b/.github/workflows/offline.yml.disabled new file mode 100644 index 000000000..8654232a0 --- /dev/null +++ b/.github/workflows/offline.yml.disabled @@ -0,0 +1,123 @@ +on: + push: + branches: [master, develop] + tags: [ v* ] + paths-ignore: + - '*.md' + - '**/*.md' + pull_request: + branches: [master, develop] + paths-ignore: + - '*.md' + - '**/*.md' +jobs: + offline: + name: Prepare offline package + # Useful to skip expensive CI when writing docs + if: "!contains(github.event.head_commit.message, 'skip ci')" + runs-on: + group: wire-server-deploy + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - uses: cachix/install-nix-action@v27 + - uses: cachix/cachix-action@v15 + with: + name: wire-server + signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}" + + - name: Install nix environment + run: nix-env -f default.nix -iA env + + - name: Get upload name + id: upload_name + run: | + # FIXME: Tag with a nice release name using the github tag... + # SOURCE_TAG=${GITHUB_REF#refs/tags/} + echo ::set-output name=UPLOAD_NAME::$GITHUB_SHA + # echo ::set-output name=UPLOAD_NAME::${SOURCE_TAG:-$GITHUB_SHA} + + # deafult profile build + - name: Process the default profile build + run: ./offline/default-build/build.sh + env: + GPG_PRIVATE_KEY: '${{ secrets.GPG_PRIVATE_KEY }}' + DOCKER_LOGIN: '${{ secrets.DOCKER_LOGIN }}' + + - name: Copy default build assets tarball to S3 and clean up + run: | + # Upload tarball for each profile by specifying their OUTPUT_TAR path + aws s3 cp offline/default-build/output/assets.tgz s3://public.wire.com/artifacts/wire-server-deploy-static-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz + echo "Uploaded to: https://s3-$AWS_REGION.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz" + # removing everything except assets.tgz as it is not required anymore in the further builds + find offline/default-build/output/ -mindepth 1 -maxdepth 1 ! -name 'assets.tgz' -exec rm -r {} + + env: + AWS_ACCESS_KEY_ID: '${{ secrets.AWS_ACCESS_KEY_ID }}' + AWS_SECRET_ACCESS_KEY: '${{ secrets.AWS_SECRET_ACCESS_KEY }}' + AWS_REGION: "eu-west-1" + + - name: Build and upload wire-server-deploy container + run: | + container_image=$(nix-build --no-out-link -A container) + skopeo copy --retry-times 10 --dest-creds "$DOCKER_LOGIN" \ + docker-archive:"$container_image" \ + "docker://quay.io/wire/wire-server-deploy:${{ steps.upload_name.outputs.UPLOAD_NAME }}" + env: + DOCKER_LOGIN: '${{ secrets.DOCKER_LOGIN }}' + + # demo profile build + - name: Process the demo profile build + run: ./offline/demo-build/build.sh + env: + GPG_PRIVATE_KEY: '${{ secrets.GPG_PRIVATE_KEY }}' + DOCKER_LOGIN: '${{ secrets.DOCKER_LOGIN }}' + + - name: Copy demo build assets tarball to S3 and clean up + run: | + # Upload tarball for each profile by specifying their OUTPUT_TAR path + aws s3 cp offline/demo-build/output/assets.tgz s3://public.wire.com/artifacts/wire-server-deploy-static-demo-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz + echo "Uploaded to: https://s3-$AWS_REGION.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-demo-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz" + # remove the assets from the build to optimize the space on the server + rm -rf offline/demo-build/output/* + env: + AWS_ACCESS_KEY_ID: '${{ secrets.AWS_ACCESS_KEY_ID }}' + AWS_SECRET_ACCESS_KEY: '${{ secrets.AWS_SECRET_ACCESS_KEY }}' + AWS_REGION: "eu-west-1" + + # min profile build + - name: Process the min profile build + run: ./offline/min-build/build.sh + env: + GPG_PRIVATE_KEY: '${{ secrets.GPG_PRIVATE_KEY }}' + DOCKER_LOGIN: '${{ secrets.DOCKER_LOGIN }}' + + - name: Copy min build assets tarball to S3 + run: | + # Upload tarball for each profile by specifying their OUTPUT_TAR path + aws s3 cp offline/min-build/output/assets.tgz s3://public.wire.com/artifacts/wire-server-deploy-static-min-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz + echo "Uploaded to: https://s3-$AWS_REGION.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-min-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz" + # remove the archives from the build to optimize the space on the server + rm -rf offline/min-build/output/* + env: + AWS_ACCESS_KEY_ID: '${{ secrets.AWS_ACCESS_KEY_ID }}' + AWS_SECRET_ACCESS_KEY: '${{ secrets.AWS_SECRET_ACCESS_KEY }}' + AWS_REGION: "eu-west-1" + + - name: Install terraform + uses: hashicorp/setup-terraform@v3 + with: + terraform_version: "^1.3.7" + terraform_wrapper: false + + - name: Deploy offline environment to hetzner with fast S3 deployment + run: | + ./offline/cd-with-retry-fast.sh + env: + HCLOUD_TOKEN: '${{ secrets.HCLOUD_TOKEN }}' + + #- name: Clean up hetzner environment; just in case + # if: always() + # run: (cd terraform/examples/wire-server-deploy-offline-hetzner ; terraform init && terraform destroy -auto-approve) + # env: + # HCLOUD_TOKEN: '${{ secrets.HCLOUD_TOKEN }}' diff --git a/changelog.d/3-deploy-builds/optimize-default-build-deploy-process b/changelog.d/3-deploy-builds/optimize-default-build-deploy-process new file mode 100644 index 000000000..90041f97c --- /dev/null +++ b/changelog.d/3-deploy-builds/optimize-default-build-deploy-process @@ -0,0 +1,5 @@ +Changed: Optimize Wire offline deployment pipeline with parallel job execution and S3 direct downloads +Added: Retry logic with progressive server type fallbacks for Hetzner Cloud resource availability issues +Changed: Implement parallel terraform operations (15 parallelism) and fast SSH connection multiplexing +Changed: Move ansible execution directly to adminhost for faster private network connectivity +Changed: Reduce CI deployment time from 60+ minutes to ~30-40 minutes through parallel builds and optimized deployment process diff --git a/offline/cd-with-retry.sh b/offline/cd-with-retry.sh index 5664545f1..3c4db14ec 100755 --- a/offline/cd-with-retry.sh +++ b/offline/cd-with-retry.sh @@ -7,12 +7,17 @@ set -euo pipefail CD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" TF_DIR="${CD_DIR}/../terraform/examples/wire-server-deploy-offline-hetzner" -ARTIFACTS_DIR="${CD_DIR}/default-build/output" # Retry configuration MAX_RETRIES=3 RETRY_DELAY=30 +# S3 configuration for fast asset download +S3_REGION="eu-west-1" + +# Get build ID from environment or use git commit +UPLOAD_NAME="${GITHUB_SHA:-$(git rev-parse HEAD)}" + echo "Wire Offline Deployment with Retry Logic" echo "========================================" @@ -25,14 +30,20 @@ trap cleanup EXIT cd "$TF_DIR" terraform init -# Retry loop for terraform apply +# Pre-calculate S3 URLs for faster deployment +DEFAULT_ASSETS_URL="https://s3-${S3_REGION}.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-${UPLOAD_NAME}.tgz" + +echo "Asset URL: $DEFAULT_ASSETS_URL" + +# Retry loop for terraform apply with performance optimizations echo "Starting deployment with automatic retry on resource unavailability..." for attempt in $(seq 1 $MAX_RETRIES); do echo "" echo "Deployment attempt $attempt of $MAX_RETRIES" date - if terraform apply -auto-approve; then + # Parallel terraform apply (infrastructure creation is the bottleneck) + if terraform apply -auto-approve -parallelism=15; then echo "Infrastructure deployment successful on attempt $attempt!" break else @@ -41,9 +52,9 @@ for attempt in $(seq 1 $MAX_RETRIES); do if [[ $attempt -lt $MAX_RETRIES ]]; then echo "Will retry with different configuration..." - # Clean up partial deployment + # Fast parallel cleanup echo "Cleaning up partial deployment..." - terraform destroy -auto-approve || true + terraform destroy -auto-approve -parallelism=15 || true # Wait for resources to potentially become available echo "Waiting ${RETRY_DELAY}s for resources to become available..." @@ -72,7 +83,7 @@ for attempt in $(seq 1 $MAX_RETRIES); do echo "" echo "This usually means:" echo " 1. High demand for Hetzner Cloud resources in EU regions" - echo " 2. Your account may have resource limits" + echo " 2. Hetzner account may have resource limits" echo " 3. Try again later when resources become available" echo "" echo "Manual solutions:" @@ -100,29 +111,70 @@ fi echo "" echo "Infrastructure ready! Proceeding with application deployment..." -# Continue with the rest of the original cd.sh logic + adminhost=$(terraform output adminhost) adminhost="${adminhost//\"/}" # remove extra quotes around the returned string ssh_private_key=$(terraform output ssh_private_key) +# Fast SSH setup eval "$(ssh-agent)" ssh-add - <<< "$ssh_private_key" -terraform output -json static-inventory > inventory.json +# Generate inventory in parallel with other setup +terraform output -json static-inventory > inventory.json & +INVENTORY_PID=$! + +# Pre-configure SSH for faster connections +SSH_OPTS="-oStrictHostKeyChecking=accept-new -oConnectionAttempts=3 -oConnectTimeout=10 -oServerAliveInterval=30" + +# Wait for inventory and convert to YAML +wait $INVENTORY_PID yq -y '.' inventory.json > inventory.yml -ssh -oStrictHostKeyChecking=accept-new -oConnectionAttempts=10 "root@$adminhost" tar xzv < "$ARTIFACTS_DIR/assets.tgz" +echo "Setting up adminhost for fast deployment..." + +# Install required tools on adminhost in parallel +ssh "$SSH_OPTS" "root@$adminhost" 'bash -s' << 'EOF' & +# Install AWS CLI and ansible dependencies for faster deployment +apt-get update -qq +apt-get install -y awscli curl python3-pip +pip3 install ansible +# Pre-create directories +mkdir -p ./ansible/inventory/offline/ +EOF + +SETUP_PID=$! + +# Copy inventory while setup is running +scp -o StrictHostKeyChecking=accept-new inventory.yml "root@$adminhost":./ansible/inventory/offline/inventory.yml + +# Wait for setup to complete +wait $SETUP_PID + +echo "Downloading assets directly from S3 to adminhost (much faster than local transfer)..." + +# Download assets directly from S3 to adminhost (MUCH faster) +ssh "$SSH_OPTS" "root@$adminhost" "curl -fsSL '$DEFAULT_ASSETS_URL' | tar xzv" -scp inventory.yml "root@$adminhost":./ansible/inventory/offline/inventory.yml +echo "Verifying deployment setup..." +ssh "$SSH_OPTS" "root@$adminhost" cat ./ansible/inventory/offline/inventory.yml || true -ssh "root@$adminhost" cat ./ansible/inventory/offline/inventory.yml || true +echo "Running optimized ansible deployment..." echo "Running ansible playbook setup_nodes.yml via adminhost ($adminhost)..." -ansible-playbook -i inventory.yml setup_nodes.yml --private-key "ssh_private_key" \ - -e "ansible_ssh_common_args='-o ProxyCommand=\"ssh -W %h:%p -q root@$adminhost -i ssh_private_key\" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'" +# Run ansible from adminhost for faster network connectivity +ssh "$SSH_OPTS" "root@$adminhost" "cd ./ansible && ansible-playbook -i inventory/offline/inventory.yml setup_nodes.yml --forks=10 -e ansible_ssh_common_args='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ControlMaster=auto -o ControlPersist=300s'" -# NOTE: Agent is forwarded; so that the adminhost can provision the other boxes -ssh -A "root@$adminhost" ./bin/offline-deploy.sh +echo "Running final Wire deployment..." +# Use SSH connection multiplexing for faster multiple connections +ssh -A -o ControlMaster=auto -o ControlPersist=300s "root@$adminhost" ./bin/offline-deploy.sh echo "" -echo "Wire offline deployment completed successfully!" \ No newline at end of file +echo "Fast Wire offline deployment completed successfully!" +echo "Performance optimizations used:" +echo " - S3 direct download instead of local transfer" +echo " - Parallel terraform operations (15 parallel resources)" +echo " - Faster SSH connection multiplexing" +echo " - Parallel ansible execution (10 forks)" +echo " - Pre-installed tools on adminhost" +echo " - Ansible runs directly on adminhost (no proxy jumps)" \ No newline at end of file diff --git a/terraform/examples/wire-server-deploy-offline-hetzner/main.tf b/terraform/examples/wire-server-deploy-offline-hetzner/main.tf index c0602c7ef..4d438ff00 100644 --- a/terraform/examples/wire-server-deploy-offline-hetzner/main.tf +++ b/terraform/examples/wire-server-deploy-offline-hetzner/main.tf @@ -56,7 +56,7 @@ resource "null_resource" "location_validation" { echo "DEPLOYMENT FAILED: No suitable location available" echo "Requested locations: ${join(", ", local.preferred_locations)}" echo "Available locations: ${join(", ", local.available_location_names)}" - echo "Please check your Hetzner Cloud region availability" + echo "Please check Hetzner Cloud region availability" exit 1 EOT } @@ -70,7 +70,7 @@ resource "null_resource" "small_server_type_validation" { echo "DEPLOYMENT FAILED: No suitable database server types available" echo "Requested types: ${join(", ", local.preferred_server_types.small)}" echo "Available types: ${join(", ", local.available_server_type_names)}" - echo "Please check server type availability in your selected region" + echo "Please check server type availability in the selected region" exit 1 EOT } @@ -84,7 +84,7 @@ resource "null_resource" "medium_server_type_validation" { echo "DEPLOYMENT FAILED: No suitable Kubernetes server types available" echo "Requested types: ${join(", ", local.preferred_server_types.medium)}" echo "Available types: ${join(", ", local.available_server_type_names)}" - echo "Please check server type availability in your selected region" + echo "Please check server type availability in the selected region" exit 1 EOT } From b78e2f42e18ee8431d9bbbba2d8d060868421627 Mon Sep 17 00:00:00 2001 From: Sukanta Date: Mon, 29 Sep 2025 10:32:03 +0200 Subject: [PATCH 06/33] Set default upload name in deploy workflow for test only --- .github/workflows/deploy-only.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy-only.yml b/.github/workflows/deploy-only.yml index c82dd418b..435beb03c 100644 --- a/.github/workflows/deploy-only.yml +++ b/.github/workflows/deploy-only.yml @@ -6,7 +6,7 @@ on: upload_name: description: 'Upload name (git SHA or tag)' required: false - default: '' + default: 'a71cbf843a79907a9eaca72f46f9f64e8a0524d8' pull_request: types: [opened, synchronize, reopened] paths: @@ -32,9 +32,9 @@ jobs: id: upload_name run: | if [ -n "${{ github.event.inputs.upload_name }}" ]; then - echo ::set-output name=UPLOAD_NAME::${{ github.event.inputs.upload_name }} + echo "UPLOAD_NAME=${{ github.event.inputs.upload_name }}" >> $GITHUB_OUTPUT else - echo ::set-output name=UPLOAD_NAME::$GITHUB_SHA + echo "UPLOAD_NAME=$GITHUB_SHA" >> $GITHUB_OUTPUT fi - name: Install terraform @@ -47,4 +47,4 @@ jobs: run: ./offline/cd-with-retry.sh env: HCLOUD_TOKEN: '${{ secrets.HCLOUD_TOKEN }}' - GITHUB_SHA: ${{ steps.upload_name.outputs.UPLOAD_NAME }} \ No newline at end of file + GITHUB_SHA: ${{ steps.upload_name.outputs.UPLOAD_NAME }} From f50dd007575f6bbe1ae442598f2588429947802a Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Mon, 29 Sep 2025 11:01:37 +0200 Subject: [PATCH 07/33] fix lint issue --- .github/workflows/deploy-only.yml | 18 +++++++++--------- .github/workflows/offline.yml | 8 ++++---- offline/cd-with-retry.sh | 18 ++++++++++++++---- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/.github/workflows/deploy-only.yml b/.github/workflows/deploy-only.yml index 435beb03c..bc63f97b7 100644 --- a/.github/workflows/deploy-only.yml +++ b/.github/workflows/deploy-only.yml @@ -4,21 +4,21 @@ on: workflow_dispatch: inputs: upload_name: - description: 'Upload name (git SHA or tag)' + description: "Upload name (git SHA or tag)" required: false - default: 'a71cbf843a79907a9eaca72f46f9f64e8a0524d8' + default: "a71cbf843a79907a9eaca72f46f9f64e8a0524d8" pull_request: types: [opened, synchronize, reopened] paths: - - 'terraform/**' - - 'offline/cd-with-retry.sh' - - '.github/workflows/deploy-only.yml' + - "terraform/**" + - "offline/cd-with-retry.sh" + - ".github/workflows/deploy-only.yml" push: branches: [master, develop] paths: - - 'terraform/**' - - 'offline/cd-with-retry.sh' - - '.github/workflows/deploy-only.yml' + - "terraform/**" + - "offline/cd-with-retry.sh" + - ".github/workflows/deploy-only.yml" jobs: deploy-only: @@ -46,5 +46,5 @@ jobs: - name: Fast deploy to Hetzner run: ./offline/cd-with-retry.sh env: - HCLOUD_TOKEN: '${{ secrets.HCLOUD_TOKEN }}' + HCLOUD_TOKEN: "${{ secrets.HCLOUD_TOKEN }}" GITHUB_SHA: ${{ steps.upload_name.outputs.UPLOAD_NAME }} diff --git a/.github/workflows/offline.yml b/.github/workflows/offline.yml index 4c8f75fe1..38c4a4b73 100644 --- a/.github/workflows/offline.yml +++ b/.github/workflows/offline.yml @@ -33,7 +33,7 @@ jobs: - name: Get upload name id: upload_name - run: echo ::set-output name=UPLOAD_NAME::$GITHUB_SHA + run: echo "UPLOAD_NAME=$GITHUB_SHA" >> $GITHUB_OUTPUT # Only build default profile for deployment - name: Process default build for deployment @@ -80,7 +80,7 @@ jobs: - name: Get upload name id: upload_name - run: echo ::set-output name=UPLOAD_NAME::$GITHUB_SHA + run: echo "UPLOAD_NAME=$GITHUB_SHA" >> $GITHUB_OUTPUT - name: Build and upload wire-server-deploy container run: | @@ -111,7 +111,7 @@ jobs: - name: Get upload name id: upload_name - run: echo ::set-output name=UPLOAD_NAME::$GITHUB_SHA + run: echo "UPLOAD_NAME=$GITHUB_SHA" >> $GITHUB_OUTPUT - name: Process demo profile build run: ./offline/demo-build/build.sh @@ -148,7 +148,7 @@ jobs: - name: Get upload name id: upload_name - run: echo ::set-output name=UPLOAD_NAME::$GITHUB_SHA + run: echo "UPLOAD_NAME=$GITHUB_SHA" >> $GITHUB_OUTPUT - name: Process min profile build run: ./offline/min-build/build.sh diff --git a/offline/cd-with-retry.sh b/offline/cd-with-retry.sh index 3c4db14ec..667d63b83 100755 --- a/offline/cd-with-retry.sh +++ b/offline/cd-with-retry.sh @@ -22,8 +22,11 @@ echo "Wire Offline Deployment with Retry Logic" echo "========================================" function cleanup { - (cd "$TF_DIR" && terraform destroy -auto-approve) - echo "Cleanup completed" + if [[ "${CLEANUP_ON_EXIT:-}" == "true" ]]; then + echo "Running cleanup..." + (cd "$TF_DIR" && terraform destroy -auto-approve) + echo "Cleanup completed" + fi } trap cleanup EXIT @@ -45,6 +48,8 @@ for attempt in $(seq 1 $MAX_RETRIES); do # Parallel terraform apply (infrastructure creation is the bottleneck) if terraform apply -auto-approve -parallelism=15; then echo "Infrastructure deployment successful on attempt $attempt!" + # Enable cleanup since infrastructure exists + export CLEANUP_ON_EXIT="true" break else echo "Infrastructure deployment failed on attempt $attempt" @@ -97,6 +102,8 @@ for attempt in $(seq 1 $MAX_RETRIES); do terraform init -reconfigure fi + # Enable cleanup for final failure case + export CLEANUP_ON_EXIT="true" exit 1 fi fi @@ -129,7 +136,7 @@ SSH_OPTS="-oStrictHostKeyChecking=accept-new -oConnectionAttempts=3 -oConnectTim # Wait for inventory and convert to YAML wait $INVENTORY_PID -yq -y '.' inventory.json > inventory.yml +yq -p json -o yaml '.' inventory.json > inventory.yml echo "Setting up adminhost for fast deployment..." @@ -177,4 +184,7 @@ echo " - Parallel terraform operations (15 parallel resources)" echo " - Faster SSH connection multiplexing" echo " - Parallel ansible execution (10 forks)" echo " - Pre-installed tools on adminhost" -echo " - Ansible runs directly on adminhost (no proxy jumps)" \ No newline at end of file +echo " - Ansible runs directly on adminhost (no proxy jumps)" + +# Enable cleanup only after successful deployment +export CLEANUP_ON_EXIT="true" \ No newline at end of file From 2b977a395945856e320e53c4bea4bcd6b2ee455b Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Mon, 29 Sep 2025 11:46:52 +0200 Subject: [PATCH 08/33] try again --- offline/cd-with-retry.sh | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/offline/cd-with-retry.sh b/offline/cd-with-retry.sh index 667d63b83..fb1826d94 100755 --- a/offline/cd-with-retry.sh +++ b/offline/cd-with-retry.sh @@ -31,6 +31,13 @@ function cleanup { trap cleanup EXIT cd "$TF_DIR" + +# Clean up any existing state to ensure fresh deployment +if [[ -f terraform.tfstate ]]; then + echo "Cleaning up existing terraform state..." + rm -f terraform.tfstate terraform.tfstate.backup +fi + terraform init # Pre-calculate S3 URLs for faster deployment @@ -136,7 +143,23 @@ SSH_OPTS="-oStrictHostKeyChecking=accept-new -oConnectionAttempts=3 -oConnectTim # Wait for inventory and convert to YAML wait $INVENTORY_PID -yq -p json -o yaml '.' inventory.json > inventory.yml + +# Ensure yq is available (fallback to python if yq not found) +if command -v yq >/dev/null 2>&1; then + yq -p json -o yaml '.' inventory.json > inventory.yml +else + echo "yq not found, using python for JSON to YAML conversion..." + python3 -c " +import json, yaml +with open('inventory.json', 'r') as f: + data = json.load(f) +with open('inventory.yml', 'w') as f: + yaml.dump(data, f, default_flow_style=False) +" || { + echo "Neither yq nor python yaml available, using jq fallback..." + jq -r . inventory.json > inventory.yml + } +fi echo "Setting up adminhost for fast deployment..." @@ -144,7 +167,7 @@ echo "Setting up adminhost for fast deployment..." ssh "$SSH_OPTS" "root@$adminhost" 'bash -s' << 'EOF' & # Install AWS CLI and ansible dependencies for faster deployment apt-get update -qq -apt-get install -y awscli curl python3-pip +apt-get install -y awscli curl python3-pip yq pip3 install ansible # Pre-create directories mkdir -p ./ansible/inventory/offline/ From d2fb76905400a714980b5177e75805608caa6e60 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Mon, 29 Sep 2025 12:03:50 +0200 Subject: [PATCH 09/33] fix script to get the supplied s3 hash --- offline/cd-with-retry.sh | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/offline/cd-with-retry.sh b/offline/cd-with-retry.sh index fb1826d94..c0e1a1c5c 100755 --- a/offline/cd-with-retry.sh +++ b/offline/cd-with-retry.sh @@ -18,6 +18,9 @@ S3_REGION="eu-west-1" # Get build ID from environment or use git commit UPLOAD_NAME="${GITHUB_SHA:-$(git rev-parse HEAD)}" +echo "Using UPLOAD_NAME: $UPLOAD_NAME" +echo "GITHUB_SHA: ${GITHUB_SHA:-not set}" + echo "Wire Offline Deployment with Retry Logic" echo "========================================" @@ -144,21 +147,13 @@ SSH_OPTS="-oStrictHostKeyChecking=accept-new -oConnectionAttempts=3 -oConnectTim # Wait for inventory and convert to YAML wait $INVENTORY_PID -# Ensure yq is available (fallback to python if yq not found) +# Convert inventory to YAML (ansible can read both JSON and YAML) if command -v yq >/dev/null 2>&1; then + echo "Converting inventory to YAML format..." yq -p json -o yaml '.' inventory.json > inventory.yml else - echo "yq not found, using python for JSON to YAML conversion..." - python3 -c " -import json, yaml -with open('inventory.json', 'r') as f: - data = json.load(f) -with open('inventory.yml', 'w') as f: - yaml.dump(data, f, default_flow_style=False) -" || { - echo "Neither yq nor python yaml available, using jq fallback..." - jq -r . inventory.json > inventory.yml - } + echo "yq not available, using JSON inventory directly (ansible supports both formats)..." + cp inventory.json inventory.yml fi echo "Setting up adminhost for fast deployment..." From accbbe14e232b410b6580e88e8651dc323cceaf0 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Mon, 29 Sep 2025 12:15:14 +0200 Subject: [PATCH 10/33] try again --- offline/cd-with-retry.sh | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/offline/cd-with-retry.sh b/offline/cd-with-retry.sh index c0e1a1c5c..4c5a16b82 100755 --- a/offline/cd-with-retry.sh +++ b/offline/cd-with-retry.sh @@ -2,12 +2,20 @@ set -euo pipefail +# Enable verbose debugging +set -x + # This is the production version of cd.sh with built-in retry logic # Use this instead of cd.sh when you want automatic resource availability handling CD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" TF_DIR="${CD_DIR}/../terraform/examples/wire-server-deploy-offline-hetzner" +echo "Script directory (CD_DIR): $CD_DIR" +echo "Terraform directory (TF_DIR): $TF_DIR" +echo "Checking if TF_DIR exists:" +ls -la "$TF_DIR" || echo "TF_DIR does not exist" + # Retry configuration MAX_RETRIES=3 RETRY_DELAY=30 @@ -33,7 +41,16 @@ function cleanup { } trap cleanup EXIT -cd "$TF_DIR" +echo "Changing to terraform directory: $TF_DIR" +cd "$TF_DIR" || { + echo "ERROR: Failed to change to terraform directory: $TF_DIR" + ls -la "$TF_DIR" || echo "Directory does not exist" + exit 1 +} + +echo "Current directory: $(pwd)" +echo "Directory contents:" +ls -la # Clean up any existing state to ensure fresh deployment if [[ -f terraform.tfstate ]]; then @@ -41,7 +58,20 @@ if [[ -f terraform.tfstate ]]; then rm -f terraform.tfstate terraform.tfstate.backup fi -terraform init +echo "Checking terraform availability..." +terraform version || { + echo "ERROR: terraform not found in PATH" + echo "PATH: $PATH" + which terraform || echo "terraform not in which" + exit 1 +} + +echo "Running terraform init..." +terraform init || { + echo "ERROR: terraform init failed" + echo "Exit code: $?" + exit 1 +} # Pre-calculate S3 URLs for faster deployment DEFAULT_ASSETS_URL="https://s3-${S3_REGION}.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-${UPLOAD_NAME}.tgz" @@ -56,6 +86,7 @@ for attempt in $(seq 1 $MAX_RETRIES); do date # Parallel terraform apply (infrastructure creation is the bottleneck) + echo "Running terraform apply with parallelism=15..." if terraform apply -auto-approve -parallelism=15; then echo "Infrastructure deployment successful on attempt $attempt!" # Enable cleanup since infrastructure exists From 5467387e84eb00b3008509b1d58fdd224db85df8 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Mon, 29 Sep 2025 13:22:00 +0200 Subject: [PATCH 11/33] WIP-1 --- offline/cd-with-retry.sh | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/offline/cd-with-retry.sh b/offline/cd-with-retry.sh index 4c5a16b82..c2ac4b3d0 100755 --- a/offline/cd-with-retry.sh +++ b/offline/cd-with-retry.sh @@ -2,8 +2,8 @@ set -euo pipefail -# Enable verbose debugging -set -x +# Enable verbose debugging (disable for cleaner output) +# set -x # This is the production version of cd.sh with built-in retry logic # Use this instead of cd.sh when you want automatic resource availability handling @@ -85,9 +85,9 @@ for attempt in $(seq 1 $MAX_RETRIES); do echo "Deployment attempt $attempt of $MAX_RETRIES" date - # Parallel terraform apply (infrastructure creation is the bottleneck) - echo "Running terraform apply with parallelism=15..." - if terraform apply -auto-approve -parallelism=15; then + # Terraform apply (temporarily removing parallelism for debugging) + echo "Running terraform apply..." + if terraform apply -auto-approve; then echo "Infrastructure deployment successful on attempt $attempt!" # Enable cleanup since infrastructure exists export CLEANUP_ON_EXIT="true" @@ -98,9 +98,9 @@ for attempt in $(seq 1 $MAX_RETRIES); do if [[ $attempt -lt $MAX_RETRIES ]]; then echo "Will retry with different configuration..." - # Fast parallel cleanup + # Cleanup partial deployment echo "Cleaning up partial deployment..." - terraform destroy -auto-approve -parallelism=15 || true + terraform destroy -auto-approve || true # Wait for resources to potentially become available echo "Waiting ${RETRY_DELAY}s for resources to become available..." @@ -165,7 +165,10 @@ adminhost="${adminhost//\"/}" # remove extra quotes around the returned string ssh_private_key=$(terraform output ssh_private_key) # Fast SSH setup -eval "$(ssh-agent)" +eval "$(ssh-agent)" || { + echo "ERROR: Failed to start ssh-agent" + exit 1 +} ssh-add - <<< "$ssh_private_key" # Generate inventory in parallel with other setup From ce45b0089a4d74a7fbe7cd31014e9cb163443c37 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Mon, 29 Sep 2025 13:47:23 +0200 Subject: [PATCH 12/33] add logging --- offline/cd-with-retry.sh | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/offline/cd-with-retry.sh b/offline/cd-with-retry.sh index c2ac4b3d0..49d9006da 100755 --- a/offline/cd-with-retry.sh +++ b/offline/cd-with-retry.sh @@ -93,7 +93,8 @@ for attempt in $(seq 1 $MAX_RETRIES); do export CLEANUP_ON_EXIT="true" break else - echo "Infrastructure deployment failed on attempt $attempt" + TERRAFORM_EXIT_CODE=$? + echo "Infrastructure deployment failed on attempt $attempt (exit code: $TERRAFORM_EXIT_CODE)" if [[ $attempt -lt $MAX_RETRIES ]]; then echo "Will retry with different configuration..." @@ -150,6 +151,12 @@ for attempt in $(seq 1 $MAX_RETRIES); do fi done +# Check if we exited the loop successfully (CLEANUP_ON_EXIT set means terraform apply succeeded) +if [[ "${CLEANUP_ON_EXIT:-}" != "true" ]]; then + echo "ERROR: All terraform attempts failed, but script continued unexpectedly" + exit 1 +fi + # Restore original config after successful deployment if [[ -f main.tf.bak ]]; then mv main.tf.bak main.tf @@ -160,9 +167,20 @@ echo "" echo "Infrastructure ready! Proceeding with application deployment..." -adminhost=$(terraform output adminhost) +echo "Getting terraform outputs..." +adminhost=$(terraform output adminhost) || { + echo "ERROR: Failed to get adminhost output from terraform" + terraform output || echo "No terraform outputs available" + exit 1 +} adminhost="${adminhost//\"/}" # remove extra quotes around the returned string -ssh_private_key=$(terraform output ssh_private_key) +echo "Adminhost IP: $adminhost" + +ssh_private_key=$(terraform output ssh_private_key) || { + echo "ERROR: Failed to get ssh_private_key output from terraform" + exit 1 +} +echo "SSH private key retrieved (length: ${#ssh_private_key} chars)" # Fast SSH setup eval "$(ssh-agent)" || { From 646ba2093f6fa7d26d7be775ce3936ed227b017c Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Mon, 29 Sep 2025 13:58:59 +0200 Subject: [PATCH 13/33] add nix env for deploy only workflow --- .github/workflows/deploy-only.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/deploy-only.yml b/.github/workflows/deploy-only.yml index bc63f97b7..41f19559e 100644 --- a/.github/workflows/deploy-only.yml +++ b/.github/workflows/deploy-only.yml @@ -27,6 +27,16 @@ jobs: group: wire-server-deploy steps: - uses: actions/checkout@v2 + with: + submodules: true + - uses: cachix/install-nix-action@v27 + - uses: cachix/cachix-action@v15 + with: + name: wire-server + signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}" + + - name: Install nix environment + run: nix-env -f default.nix -iA env - name: Get upload name id: upload_name From f180ed2d031e8b2d7c4eccc78967efa76e122910 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Mon, 29 Sep 2025 14:23:25 +0200 Subject: [PATCH 14/33] one more time --- offline/cd-with-retry.sh | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/offline/cd-with-retry.sh b/offline/cd-with-retry.sh index 49d9006da..e107ab913 100755 --- a/offline/cd-with-retry.sh +++ b/offline/cd-with-retry.sh @@ -229,9 +229,35 @@ scp -o StrictHostKeyChecking=accept-new inventory.yml "root@$adminhost":./ansibl wait $SETUP_PID echo "Downloading assets directly from S3 to adminhost (much faster than local transfer)..." +echo "S3 URL: $DEFAULT_ASSETS_URL" -# Download assets directly from S3 to adminhost (MUCH faster) -ssh "$SSH_OPTS" "root@$adminhost" "curl -fsSL '$DEFAULT_ASSETS_URL' | tar xzv" +# Test S3 URL accessibility first +echo "Testing S3 URL accessibility..." +if curl -I -s "$DEFAULT_ASSETS_URL" | head -1 | grep -q "200 OK"; then + echo "โœ… S3 asset is accessible" +else + echo "โŒ S3 asset is not accessible" + echo "Response:" + curl -I -s "$DEFAULT_ASSETS_URL" | head -5 + exit 1 +fi + +# Download assets to local temp and transfer (fallback to working pattern) +echo "Downloading assets locally first, then transferring..." +TEMP_ASSETS="/tmp/assets.tgz" +curl -fsSL "$DEFAULT_ASSETS_URL" -o "$TEMP_ASSETS" || { + echo "ERROR: Failed to download assets from S3" + exit 1 +} + +echo "Transferring assets to adminhost..." +ssh "$SSH_OPTS" "root@$adminhost" tar xzv < "$TEMP_ASSETS" || { + echo "ERROR: Failed to transfer/extract assets to adminhost" + exit 1 +} + +echo "Cleaning up local temp assets..." +rm -f "$TEMP_ASSETS" echo "Verifying deployment setup..." ssh "$SSH_OPTS" "root@$adminhost" cat ./ansible/inventory/offline/inventory.yml || true From 4e0a332da345789924d03d9fbd291fd2a014aec0 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Mon, 29 Sep 2025 17:27:20 +0200 Subject: [PATCH 15/33] try parallel deployment and copy from local assets --- .github/workflows/deploy-only.yml | 33 +++-- .github/workflows/offline.yml | 149 ++++++++++++------- offline/cd-with-retry.sh | 229 +++++++----------------------- offline/cd.sh | 2 +- 4 files changed, 165 insertions(+), 248 deletions(-) diff --git a/.github/workflows/deploy-only.yml b/.github/workflows/deploy-only.yml index 41f19559e..caef2226c 100644 --- a/.github/workflows/deploy-only.yml +++ b/.github/workflows/deploy-only.yml @@ -6,28 +6,24 @@ on: upload_name: description: "Upload name (git SHA or tag)" required: false - default: "a71cbf843a79907a9eaca72f46f9f64e8a0524d8" - pull_request: - types: [opened, synchronize, reopened] - paths: - - "terraform/**" - - "offline/cd-with-retry.sh" - - ".github/workflows/deploy-only.yml" - push: - branches: [master, develop] - paths: - - "terraform/**" - - "offline/cd-with-retry.sh" - - ".github/workflows/deploy-only.yml" + default: "" + issue_comment: + types: [created] jobs: deploy-only: name: Deploy existing build + if: | + github.event_name == 'workflow_dispatch' || + (github.event_name == 'issue_comment' && + github.event.issue.pull_request && + contains(github.event.comment.body, 'deploy-')) runs-on: group: wire-server-deploy steps: - uses: actions/checkout@v2 with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} submodules: true - uses: cachix/install-nix-action@v27 - uses: cachix/cachix-action@v15 @@ -43,6 +39,17 @@ jobs: run: | if [ -n "${{ github.event.inputs.upload_name }}" ]; then echo "UPLOAD_NAME=${{ github.event.inputs.upload_name }}" >> $GITHUB_OUTPUT + elif [ "${{ github.event_name }}" = "issue_comment" ]; then + # Extract upload_name from comment like "deploy-a71cbf843a79907a9eaca72f46f9f64e8a0524d8" + COMMENT_BODY="${{ github.event.comment.body }}" + UPLOAD_NAME=$(echo "$COMMENT_BODY" | grep -o 'deploy-[a-zA-Z0-9_-]*' | head -1 | sed 's/deploy-//') + if [ -n "$UPLOAD_NAME" ]; then + echo "UPLOAD_NAME=$UPLOAD_NAME" >> $GITHUB_OUTPUT + echo "Extracted upload name from comment: $UPLOAD_NAME" + else + echo "UPLOAD_NAME=${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT + echo "No upload name found in comment, using PR head SHA" + fi else echo "UPLOAD_NAME=$GITHUB_SHA" >> $GITHUB_OUTPUT fi diff --git a/.github/workflows/offline.yml b/.github/workflows/offline.yml index 38c4a4b73..a3dfd37ea 100644 --- a/.github/workflows/offline.yml +++ b/.github/workflows/offline.yml @@ -1,23 +1,24 @@ on: push: branches: [master, develop] - tags: [v*] + tags: [ v* ] paths-ignore: - - "*.md" - - "**/*.md" + - '*.md' + - '**/*.md' pull_request: branches: [master, develop] paths-ignore: - - "*.md" - - "**/*.md" - + - '*.md' + - '**/*.md' jobs: - # Fast-track deployment job - runs in parallel with builds - deploy: - name: Build and Deploy default build + # Build default profile and create local assets + build-default: + name: Build default profile if: "!contains(github.event.head_commit.message, 'skip ci')" runs-on: group: wire-server-deploy + outputs: + upload_name: ${{ steps.upload_name.outputs.UPLOAD_NAME }} steps: - uses: actions/checkout@v2 with: @@ -35,37 +36,87 @@ jobs: id: upload_name run: echo "UPLOAD_NAME=$GITHUB_SHA" >> $GITHUB_OUTPUT - # Only build default profile for deployment - - name: Process default build for deployment + # default profile build + - name: Process the default profile build run: ./offline/default-build/build.sh env: - GPG_PRIVATE_KEY: "${{ secrets.GPG_PRIVATE_KEY }}" - DOCKER_LOGIN: "${{ secrets.DOCKER_LOGIN }}" + GPG_PRIVATE_KEY: '${{ secrets.GPG_PRIVATE_KEY }}' + DOCKER_LOGIN: '${{ secrets.DOCKER_LOGIN }}' + + # Upload the assets to be shared with other jobs + - name: Upload build artifacts + uses: actions/upload-artifact@v3 + with: + name: default-build-assets + path: offline/default-build/output/assets.tgz + retention-days: 1 + + # Upload to S3 in parallel with deployment + upload-s3: + name: Upload default build to S3 + needs: build-default + runs-on: + group: wire-server-deploy + steps: + - uses: actions/checkout@v2 + with: + submodules: true + + - name: Download build artifacts + uses: actions/download-artifact@v3 + with: + name: default-build-assets + path: offline/default-build/output/ - - name: Upload default build to S3 + - name: Copy default build assets tarball to S3 run: | - aws s3 cp offline/default-build/output/assets.tgz s3://public.wire.com/artifacts/wire-server-deploy-static-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz - echo "Uploaded to: https://s3-$AWS_REGION.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz" + aws s3 cp offline/default-build/output/assets.tgz s3://public.wire.com/artifacts/wire-server-deploy-static-${{ needs.build-default.outputs.upload_name }}.tgz + echo "Uploaded to: https://s3-$AWS_REGION.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-${{ needs.build-default.outputs.upload_name }}.tgz" env: - AWS_ACCESS_KEY_ID: "${{ secrets.AWS_ACCESS_KEY_ID }}" - AWS_SECRET_ACCESS_KEY: "${{ secrets.AWS_SECRET_ACCESS_KEY }}" + AWS_ACCESS_KEY_ID: '${{ secrets.AWS_ACCESS_KEY_ID }}' + AWS_SECRET_ACCESS_KEY: '${{ secrets.AWS_SECRET_ACCESS_KEY }}' AWS_REGION: "eu-west-1" + # Deploy to Hetzner in parallel with S3 upload + deploy-hetzner: + name: Deploy to Hetzner + needs: build-default + runs-on: + group: wire-server-deploy + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - uses: cachix/install-nix-action@v27 + - uses: cachix/cachix-action@v15 + with: + name: wire-server + signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}" + + - name: Install nix environment + run: nix-env -f default.nix -iA env + + - name: Download build artifacts + uses: actions/download-artifact@v3 + with: + name: default-build-assets + path: offline/default-build/output/ + - name: Install terraform uses: hashicorp/setup-terraform@v3 with: terraform_version: "^1.3.7" terraform_wrapper: false - - name: Deploy to Hetzner with fast S3 deployment + - name: Deploy offline environment to hetzner run: ./offline/cd-with-retry.sh env: - HCLOUD_TOKEN: "${{ secrets.HCLOUD_TOKEN }}" + HCLOUD_TOKEN: '${{ secrets.HCLOUD_TOKEN }}' - # Parallel builds for other profiles + # Build container in parallel build-container: name: Build container - if: "!contains(github.event.head_commit.message, 'skip ci')" + needs: build-default runs-on: group: wire-server-deploy steps: @@ -78,22 +129,19 @@ jobs: name: wire-server signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}" - - name: Get upload name - id: upload_name - run: echo "UPLOAD_NAME=$GITHUB_SHA" >> $GITHUB_OUTPUT - - name: Build and upload wire-server-deploy container run: | container_image=$(nix-build --no-out-link -A container) skopeo copy --retry-times 10 --dest-creds "$DOCKER_LOGIN" \ docker-archive:"$container_image" \ - "docker://quay.io/wire/wire-server-deploy:${{ steps.upload_name.outputs.UPLOAD_NAME }}" + "docker://quay.io/wire/wire-server-deploy:${{ needs.build-default.outputs.upload_name }}" env: - DOCKER_LOGIN: "${{ secrets.DOCKER_LOGIN }}" + DOCKER_LOGIN: '${{ secrets.DOCKER_LOGIN }}' + # Build demo profile build-demo: name: Build demo profile - if: "!contains(github.event.head_commit.message, 'skip ci')" + needs: build-default runs-on: group: wire-server-deploy steps: @@ -109,28 +157,25 @@ jobs: - name: Install nix environment run: nix-env -f default.nix -iA env - - name: Get upload name - id: upload_name - run: echo "UPLOAD_NAME=$GITHUB_SHA" >> $GITHUB_OUTPUT - - - name: Process demo profile build + - name: Process the demo profile build run: ./offline/demo-build/build.sh env: - GPG_PRIVATE_KEY: "${{ secrets.GPG_PRIVATE_KEY }}" - DOCKER_LOGIN: "${{ secrets.DOCKER_LOGIN }}" + GPG_PRIVATE_KEY: '${{ secrets.GPG_PRIVATE_KEY }}' + DOCKER_LOGIN: '${{ secrets.DOCKER_LOGIN }}' - - name: Upload demo build to S3 + - name: Copy demo build assets tarball to S3 run: | - aws s3 cp offline/demo-build/output/assets.tgz s3://public.wire.com/artifacts/wire-server-deploy-static-demo-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz - echo "Uploaded to: https://s3-$AWS_REGION.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-demo-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz" + aws s3 cp offline/demo-build/output/assets.tgz s3://public.wire.com/artifacts/wire-server-deploy-static-demo-${{ needs.build-default.outputs.upload_name }}.tgz + echo "Uploaded to: https://s3-$AWS_REGION.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-demo-${{ needs.build-default.outputs.upload_name }}.tgz" env: - AWS_ACCESS_KEY_ID: "${{ secrets.AWS_ACCESS_KEY_ID }}" - AWS_SECRET_ACCESS_KEY: "${{ secrets.AWS_SECRET_ACCESS_KEY }}" + AWS_ACCESS_KEY_ID: '${{ secrets.AWS_ACCESS_KEY_ID }}' + AWS_SECRET_ACCESS_KEY: '${{ secrets.AWS_SECRET_ACCESS_KEY }}' AWS_REGION: "eu-west-1" + # Build min profile build-min: name: Build min profile - if: "!contains(github.event.head_commit.message, 'skip ci')" + needs: build-default runs-on: group: wire-server-deploy steps: @@ -146,21 +191,17 @@ jobs: - name: Install nix environment run: nix-env -f default.nix -iA env - - name: Get upload name - id: upload_name - run: echo "UPLOAD_NAME=$GITHUB_SHA" >> $GITHUB_OUTPUT - - - name: Process min profile build + - name: Process the min profile build run: ./offline/min-build/build.sh env: - GPG_PRIVATE_KEY: "${{ secrets.GPG_PRIVATE_KEY }}" - DOCKER_LOGIN: "${{ secrets.DOCKER_LOGIN }}" + GPG_PRIVATE_KEY: '${{ secrets.GPG_PRIVATE_KEY }}' + DOCKER_LOGIN: '${{ secrets.DOCKER_LOGIN }}' - - name: Upload min build to S3 + - name: Copy min build assets tarball to S3 run: | - aws s3 cp offline/min-build/output/assets.tgz s3://public.wire.com/artifacts/wire-server-deploy-static-min-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz - echo "Uploaded to: https://s3-$AWS_REGION.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-min-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz" + aws s3 cp offline/min-build/output/assets.tgz s3://public.wire.com/artifacts/wire-server-deploy-static-min-${{ needs.build-default.outputs.upload_name }}.tgz + echo "Uploaded to: https://s3-$AWS_REGION.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-min-${{ needs.build-default.outputs.upload_name }}.tgz" env: - AWS_ACCESS_KEY_ID: "${{ secrets.AWS_ACCESS_KEY_ID }}" - AWS_SECRET_ACCESS_KEY: "${{ secrets.AWS_SECRET_ACCESS_KEY }}" + AWS_ACCESS_KEY_ID: '${{ secrets.AWS_ACCESS_KEY_ID }}' + AWS_SECRET_ACCESS_KEY: '${{ secrets.AWS_SECRET_ACCESS_KEY }}' AWS_REGION: "eu-west-1" diff --git a/offline/cd-with-retry.sh b/offline/cd-with-retry.sh index e107ab913..86cb7d113 100755 --- a/offline/cd-with-retry.sh +++ b/offline/cd-with-retry.sh @@ -2,104 +2,73 @@ set -euo pipefail -# Enable verbose debugging (disable for cleaner output) -# set -x - # This is the production version of cd.sh with built-in retry logic # Use this instead of cd.sh when you want automatic resource availability handling CD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" TF_DIR="${CD_DIR}/../terraform/examples/wire-server-deploy-offline-hetzner" +ARTIFACTS_DIR="${CD_DIR}/default-build/output" -echo "Script directory (CD_DIR): $CD_DIR" -echo "Terraform directory (TF_DIR): $TF_DIR" -echo "Checking if TF_DIR exists:" -ls -la "$TF_DIR" || echo "TF_DIR does not exist" +# S3 configuration for asset download fallback +S3_REGION="eu-west-1" +UPLOAD_NAME="${GITHUB_SHA:-$(git rev-parse HEAD 2>/dev/null || echo 'unknown')}" -# Retry configuration -MAX_RETRIES=3 -RETRY_DELAY=30 +# Ensure assets are available (download from S3 if local assets don't exist) +if [[ ! -f "$ARTIFACTS_DIR/assets.tgz" && -n "${GITHUB_SHA:-}" ]]; then + echo "Local assets not found. Downloading from S3..." + echo "Using UPLOAD_NAME: $UPLOAD_NAME" -# S3 configuration for fast asset download -S3_REGION="eu-west-1" + mkdir -p "$ARTIFACTS_DIR" + S3_URL="https://s3-${S3_REGION}.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-${UPLOAD_NAME}.tgz" -# Get build ID from environment or use git commit -UPLOAD_NAME="${GITHUB_SHA:-$(git rev-parse HEAD)}" + if curl -fsSL "$S3_URL" -o "$ARTIFACTS_DIR/assets.tgz"; then + echo "Successfully downloaded assets from S3" + else + echo "ERROR: Failed to download assets from S3: $S3_URL" + echo "Please ensure the build artifacts exist or run the full build first" + exit 1 + fi +elif [[ -f "$ARTIFACTS_DIR/assets.tgz" ]]; then + echo "Using existing local assets: $ARTIFACTS_DIR/assets.tgz" +else + echo "ERROR: No assets available and no GITHUB_SHA set for S3 download" + echo "Please run the build first or set GITHUB_SHA environment variable" + exit 1 +fi -echo "Using UPLOAD_NAME: $UPLOAD_NAME" -echo "GITHUB_SHA: ${GITHUB_SHA:-not set}" +# Retry configuration +MAX_RETRIES=3 +RETRY_DELAY=30 echo "Wire Offline Deployment with Retry Logic" echo "========================================" function cleanup { - if [[ "${CLEANUP_ON_EXIT:-}" == "true" ]]; then - echo "Running cleanup..." - (cd "$TF_DIR" && terraform destroy -auto-approve) - echo "Cleanup completed" - fi + (cd "$TF_DIR" && terraform destroy -auto-approve) + echo "Cleanup completed" } trap cleanup EXIT -echo "Changing to terraform directory: $TF_DIR" -cd "$TF_DIR" || { - echo "ERROR: Failed to change to terraform directory: $TF_DIR" - ls -la "$TF_DIR" || echo "Directory does not exist" - exit 1 -} - -echo "Current directory: $(pwd)" -echo "Directory contents:" -ls -la - -# Clean up any existing state to ensure fresh deployment -if [[ -f terraform.tfstate ]]; then - echo "Cleaning up existing terraform state..." - rm -f terraform.tfstate terraform.tfstate.backup -fi - -echo "Checking terraform availability..." -terraform version || { - echo "ERROR: terraform not found in PATH" - echo "PATH: $PATH" - which terraform || echo "terraform not in which" - exit 1 -} +cd "$TF_DIR" +terraform init -echo "Running terraform init..." -terraform init || { - echo "ERROR: terraform init failed" - echo "Exit code: $?" - exit 1 -} - -# Pre-calculate S3 URLs for faster deployment -DEFAULT_ASSETS_URL="https://s3-${S3_REGION}.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-${UPLOAD_NAME}.tgz" - -echo "Asset URL: $DEFAULT_ASSETS_URL" - -# Retry loop for terraform apply with performance optimizations +# Retry loop for terraform apply echo "Starting deployment with automatic retry on resource unavailability..." for attempt in $(seq 1 $MAX_RETRIES); do echo "" echo "Deployment attempt $attempt of $MAX_RETRIES" date - # Terraform apply (temporarily removing parallelism for debugging) - echo "Running terraform apply..." if terraform apply -auto-approve; then echo "Infrastructure deployment successful on attempt $attempt!" - # Enable cleanup since infrastructure exists - export CLEANUP_ON_EXIT="true" break else - TERRAFORM_EXIT_CODE=$? - echo "Infrastructure deployment failed on attempt $attempt (exit code: $TERRAFORM_EXIT_CODE)" + echo "Infrastructure deployment failed on attempt $attempt" if [[ $attempt -lt $MAX_RETRIES ]]; then echo "Will retry with different configuration..." - # Cleanup partial deployment + # Clean up partial deployment echo "Cleaning up partial deployment..." terraform destroy -auto-approve || true @@ -130,7 +99,7 @@ for attempt in $(seq 1 $MAX_RETRIES); do echo "" echo "This usually means:" echo " 1. High demand for Hetzner Cloud resources in EU regions" - echo " 2. Hetzner account may have resource limits" + echo " 2. Your account may have resource limits" echo " 3. Try again later when resources become available" echo "" echo "Manual solutions:" @@ -144,19 +113,11 @@ for attempt in $(seq 1 $MAX_RETRIES); do terraform init -reconfigure fi - # Enable cleanup for final failure case - export CLEANUP_ON_EXIT="true" exit 1 fi fi done -# Check if we exited the loop successfully (CLEANUP_ON_EXIT set means terraform apply succeeded) -if [[ "${CLEANUP_ON_EXIT:-}" != "true" ]]; then - echo "ERROR: All terraform attempts failed, but script continued unexpectedly" - exit 1 -fi - # Restore original config after successful deployment if [[ -f main.tf.bak ]]; then mv main.tf.bak main.tf @@ -166,121 +127,29 @@ fi echo "" echo "Infrastructure ready! Proceeding with application deployment..." - -echo "Getting terraform outputs..." -adminhost=$(terraform output adminhost) || { - echo "ERROR: Failed to get adminhost output from terraform" - terraform output || echo "No terraform outputs available" - exit 1 -} +# Continue with the rest of the original cd.sh logic +adminhost=$(terraform output adminhost) adminhost="${adminhost//\"/}" # remove extra quotes around the returned string -echo "Adminhost IP: $adminhost" - -ssh_private_key=$(terraform output ssh_private_key) || { - echo "ERROR: Failed to get ssh_private_key output from terraform" - exit 1 -} -echo "SSH private key retrieved (length: ${#ssh_private_key} chars)" +ssh_private_key=$(terraform output ssh_private_key) -# Fast SSH setup -eval "$(ssh-agent)" || { - echo "ERROR: Failed to start ssh-agent" - exit 1 -} +eval "$(ssh-agent)" ssh-add - <<< "$ssh_private_key" -# Generate inventory in parallel with other setup -terraform output -json static-inventory > inventory.json & -INVENTORY_PID=$! - -# Pre-configure SSH for faster connections -SSH_OPTS="-oStrictHostKeyChecking=accept-new -oConnectionAttempts=3 -oConnectTimeout=10 -oServerAliveInterval=30" - -# Wait for inventory and convert to YAML -wait $INVENTORY_PID - -# Convert inventory to YAML (ansible can read both JSON and YAML) -if command -v yq >/dev/null 2>&1; then - echo "Converting inventory to YAML format..." - yq -p json -o yaml '.' inventory.json > inventory.yml -else - echo "yq not available, using JSON inventory directly (ansible supports both formats)..." - cp inventory.json inventory.yml -fi - -echo "Setting up adminhost for fast deployment..." - -# Install required tools on adminhost in parallel -ssh "$SSH_OPTS" "root@$adminhost" 'bash -s' << 'EOF' & -# Install AWS CLI and ansible dependencies for faster deployment -apt-get update -qq -apt-get install -y awscli curl python3-pip yq -pip3 install ansible -# Pre-create directories -mkdir -p ./ansible/inventory/offline/ -EOF +terraform output -json static-inventory > inventory.json +yq eval -P '.' inventory.json > inventory.yml -SETUP_PID=$! +ssh -oStrictHostKeyChecking=accept-new -oConnectionAttempts=10 "root@$adminhost" tar xzv < "$ARTIFACTS_DIR/assets.tgz" -# Copy inventory while setup is running -scp -o StrictHostKeyChecking=accept-new inventory.yml "root@$adminhost":./ansible/inventory/offline/inventory.yml +scp inventory.yml "root@$adminhost":./ansible/inventory/offline/inventory.yml -# Wait for setup to complete -wait $SETUP_PID - -echo "Downloading assets directly from S3 to adminhost (much faster than local transfer)..." -echo "S3 URL: $DEFAULT_ASSETS_URL" - -# Test S3 URL accessibility first -echo "Testing S3 URL accessibility..." -if curl -I -s "$DEFAULT_ASSETS_URL" | head -1 | grep -q "200 OK"; then - echo "โœ… S3 asset is accessible" -else - echo "โŒ S3 asset is not accessible" - echo "Response:" - curl -I -s "$DEFAULT_ASSETS_URL" | head -5 - exit 1 -fi - -# Download assets to local temp and transfer (fallback to working pattern) -echo "Downloading assets locally first, then transferring..." -TEMP_ASSETS="/tmp/assets.tgz" -curl -fsSL "$DEFAULT_ASSETS_URL" -o "$TEMP_ASSETS" || { - echo "ERROR: Failed to download assets from S3" - exit 1 -} - -echo "Transferring assets to adminhost..." -ssh "$SSH_OPTS" "root@$adminhost" tar xzv < "$TEMP_ASSETS" || { - echo "ERROR: Failed to transfer/extract assets to adminhost" - exit 1 -} - -echo "Cleaning up local temp assets..." -rm -f "$TEMP_ASSETS" - -echo "Verifying deployment setup..." -ssh "$SSH_OPTS" "root@$adminhost" cat ./ansible/inventory/offline/inventory.yml || true - -echo "Running optimized ansible deployment..." +ssh "root@$adminhost" cat ./ansible/inventory/offline/inventory.yml || true echo "Running ansible playbook setup_nodes.yml via adminhost ($adminhost)..." -# Run ansible from adminhost for faster network connectivity -ssh "$SSH_OPTS" "root@$adminhost" "cd ./ansible && ansible-playbook -i inventory/offline/inventory.yml setup_nodes.yml --forks=10 -e ansible_ssh_common_args='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ControlMaster=auto -o ControlPersist=300s'" +ansible-playbook -i inventory.yml setup_nodes.yml --private-key "ssh_private_key" \ + -e "ansible_ssh_common_args='-o ProxyCommand=\"ssh -W %h:%p -q root@$adminhost -i ssh_private_key\" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'" -echo "Running final Wire deployment..." -# Use SSH connection multiplexing for faster multiple connections -ssh -A -o ControlMaster=auto -o ControlPersist=300s "root@$adminhost" ./bin/offline-deploy.sh +# NOTE: Agent is forwarded; so that the adminhost can provision the other boxes +ssh -A "root@$adminhost" ./bin/offline-deploy.sh echo "" -echo "Fast Wire offline deployment completed successfully!" -echo "Performance optimizations used:" -echo " - S3 direct download instead of local transfer" -echo " - Parallel terraform operations (15 parallel resources)" -echo " - Faster SSH connection multiplexing" -echo " - Parallel ansible execution (10 forks)" -echo " - Pre-installed tools on adminhost" -echo " - Ansible runs directly on adminhost (no proxy jumps)" - -# Enable cleanup only after successful deployment -export CLEANUP_ON_EXIT="true" \ No newline at end of file +echo "Wire offline deployment completed successfully!" \ No newline at end of file diff --git a/offline/cd.sh b/offline/cd.sh index 53038b865..5a471afc9 100755 --- a/offline/cd.sh +++ b/offline/cd.sh @@ -24,7 +24,7 @@ eval `ssh-agent` ssh-add - <<< "$ssh_private_key" terraform output -json static-inventory > inventory.json -yq -y '.' inventory.json > inventory.yml +yq eval -P '.' inventory.json > inventory.yml ssh -oStrictHostKeyChecking=accept-new -oConnectionAttempts=10 "root@$adminhost" tar xzv < "$ARTIFACTS_DIR/assets.tgz" From 02914dd83e654fb06d9a8aae55459947949e33fa Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Mon, 29 Sep 2025 17:39:41 +0200 Subject: [PATCH 16/33] run again --- .github/workflows/offline.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/offline.yml b/.github/workflows/offline.yml index a3dfd37ea..4955b801a 100644 --- a/.github/workflows/offline.yml +++ b/.github/workflows/offline.yml @@ -13,7 +13,7 @@ on: jobs: # Build default profile and create local assets build-default: - name: Build default profile + name: Prepare offline package if: "!contains(github.event.head_commit.message, 'skip ci')" runs-on: group: wire-server-deploy @@ -45,7 +45,7 @@ jobs: # Upload the assets to be shared with other jobs - name: Upload build artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: default-build-assets path: offline/default-build/output/assets.tgz @@ -54,6 +54,7 @@ jobs: # Upload to S3 in parallel with deployment upload-s3: name: Upload default build to S3 + if: "!contains(github.event.head_commit.message, 'skip ci')" needs: build-default runs-on: group: wire-server-deploy @@ -63,7 +64,7 @@ jobs: submodules: true - name: Download build artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: default-build-assets path: offline/default-build/output/ @@ -80,6 +81,7 @@ jobs: # Deploy to Hetzner in parallel with S3 upload deploy-hetzner: name: Deploy to Hetzner + if: "!contains(github.event.head_commit.message, 'skip ci')" needs: build-default runs-on: group: wire-server-deploy @@ -97,7 +99,7 @@ jobs: run: nix-env -f default.nix -iA env - name: Download build artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: default-build-assets path: offline/default-build/output/ @@ -116,6 +118,7 @@ jobs: # Build container in parallel build-container: name: Build container + if: "!contains(github.event.head_commit.message, 'skip ci')" needs: build-default runs-on: group: wire-server-deploy @@ -141,6 +144,7 @@ jobs: # Build demo profile build-demo: name: Build demo profile + if: "!contains(github.event.head_commit.message, 'skip ci')" needs: build-default runs-on: group: wire-server-deploy @@ -175,6 +179,7 @@ jobs: # Build min profile build-min: name: Build min profile + if: "!contains(github.event.head_commit.message, 'skip ci')" needs: build-default runs-on: group: wire-server-deploy From 2c0e1abde8c89412c1d6afc7dc2eab9d176e0d75 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Mon, 29 Sep 2025 17:53:59 +0200 Subject: [PATCH 17/33] replace bitnami with bitnamilegacy --- .github/workflows/offline.yml | 2 +- nix/scripts/list-helm-containers.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/offline.yml b/.github/workflows/offline.yml index 4955b801a..f6fabfdb6 100644 --- a/.github/workflows/offline.yml +++ b/.github/workflows/offline.yml @@ -13,7 +13,7 @@ on: jobs: # Build default profile and create local assets build-default: - name: Prepare offline package + name: Build default profile if: "!contains(github.event.head_commit.message, 'skip ci')" runs-on: group: wire-server-deploy diff --git a/nix/scripts/list-helm-containers.sh b/nix/scripts/list-helm-containers.sh index 204df5ba9..8a35b6fd1 100644 --- a/nix/scripts/list-helm-containers.sh +++ b/nix/scripts/list-helm-containers.sh @@ -81,7 +81,7 @@ while IFS= read -r chart; do --set federate.dtls.tls.crt=emptyString \ $( [[ -f "${VALUES_DIR}"/$(basename "${chart}")/"${VALUES_TYPE}"-values.example.yaml ]] && echo "-f ${VALUES_DIR}/$(basename "${chart}")/${VALUES_TYPE}-values.example.yaml" ) \ $( [[ -f "${VALUES_DIR}"/$(basename "${chart}")/"${VALUES_TYPE}"-secrets.example.yaml ]] && echo "-f ${VALUES_DIR}/$(basename "${chart}")/${VALUES_TYPE}-secrets.example.yaml" ) \ - | yq -r '..|.image? | select(.)' | optionally_complain | sort -u) + | yq -r '..|.image? | select(.)' | sed 's|^bitnami/|bitnamilegacy/|g' | optionally_complain | sort -u) images+="$current_images\n" if [[ -n "$current_images" ]]; then From fa7bbb2d3fd25160fd8139cd35e200c5c790cca7 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Tue, 30 Sep 2025 10:48:36 +0200 Subject: [PATCH 18/33] fix: bintami/nginx fetch issue --- nix/scripts/list-helm-containers.sh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) mode change 100644 => 100755 nix/scripts/list-helm-containers.sh diff --git a/nix/scripts/list-helm-containers.sh b/nix/scripts/list-helm-containers.sh old mode 100644 new mode 100755 index 8a35b6fd1..0c7d3fa1a --- a/nix/scripts/list-helm-containers.sh +++ b/nix/scripts/list-helm-containers.sh @@ -76,12 +76,22 @@ images="" # render the charts, and assemble the list of images this would fetch. while IFS= read -r chart; do echo "Running helm template on chart ${chart}โ€ฆ" >&2 - current_images=$(helm template --debug "${chart}" \ + # Extract raw images before replacement + raw_images=$(helm template --debug "${chart}" \ --set federate.dtls.tls.key=emptyString \ --set federate.dtls.tls.crt=emptyString \ $( [[ -f "${VALUES_DIR}"/$(basename "${chart}")/"${VALUES_TYPE}"-values.example.yaml ]] && echo "-f ${VALUES_DIR}/$(basename "${chart}")/${VALUES_TYPE}-values.example.yaml" ) \ $( [[ -f "${VALUES_DIR}"/$(basename "${chart}")/"${VALUES_TYPE}"-secrets.example.yaml ]] && echo "-f ${VALUES_DIR}/$(basename "${chart}")/${VALUES_TYPE}-secrets.example.yaml" ) \ - | yq -r '..|.image? | select(.)' | sed 's|^bitnami/|bitnamilegacy/|g' | optionally_complain | sort -u) + | yq -r '..|.image? | select(.)') + + # Check for bitnami images before replacement + if echo "$raw_images" | grep -q "^bitnami/"; then + echo "DEBUG: Found bitnami images in chart $(basename $chart):" >&2 + echo "$raw_images" | grep "^bitnami/" >&2 + fi + + # Apply sed replacement and other processing + current_images=$(echo "$raw_images" | sed -e 's|^bitnami/|bitnamilegacy/|g' -e 's|^docker\.io/bitnami/|docker.io/bitnamilegacy/|g' | optionally_complain | sort -u) images+="$current_images\n" if [[ -n "$current_images" ]]; then From 8066a733c83d3826400e199fed6e67841f27112e Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Tue, 30 Sep 2025 11:47:06 +0200 Subject: [PATCH 19/33] fix chart with no image issue --- nix/scripts/list-helm-containers.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/scripts/list-helm-containers.sh b/nix/scripts/list-helm-containers.sh index 0c7d3fa1a..fa96ac529 100755 --- a/nix/scripts/list-helm-containers.sh +++ b/nix/scripts/list-helm-containers.sh @@ -82,7 +82,7 @@ while IFS= read -r chart; do --set federate.dtls.tls.crt=emptyString \ $( [[ -f "${VALUES_DIR}"/$(basename "${chart}")/"${VALUES_TYPE}"-values.example.yaml ]] && echo "-f ${VALUES_DIR}/$(basename "${chart}")/${VALUES_TYPE}-values.example.yaml" ) \ $( [[ -f "${VALUES_DIR}"/$(basename "${chart}")/"${VALUES_TYPE}"-secrets.example.yaml ]] && echo "-f ${VALUES_DIR}/$(basename "${chart}")/${VALUES_TYPE}-secrets.example.yaml" ) \ - | yq -r '..|.image? | select(.)') + | yq -r '..|.image?' | grep -v "^null$" | grep -v "^---$" | grep -v "^$") # Check for bitnami images before replacement if echo "$raw_images" | grep -q "^bitnami/"; then From 046e3be85d054df3dce233ee16c05fb7a735b5e7 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Tue, 30 Sep 2025 12:36:20 +0200 Subject: [PATCH 20/33] fix hanging issues --- nix/scripts/list-helm-containers.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/scripts/list-helm-containers.sh b/nix/scripts/list-helm-containers.sh index fa96ac529..e1d81b70d 100755 --- a/nix/scripts/list-helm-containers.sh +++ b/nix/scripts/list-helm-containers.sh @@ -91,7 +91,7 @@ while IFS= read -r chart; do fi # Apply sed replacement and other processing - current_images=$(echo "$raw_images" | sed -e 's|^bitnami/|bitnamilegacy/|g' -e 's|^docker\.io/bitnami/|docker.io/bitnamilegacy/|g' | optionally_complain | sort -u) + current_images=$(echo "$raw_images" | sed -e 's|^bitnami/|bitnamilegacy/|g' -e 's|^docker\.io/bitnami/|docker.io/bitnamilegacy/|g' | grep -v "^$" | optionally_complain | sort -u) images+="$current_images\n" if [[ -n "$current_images" ]]; then From bd1a4ddd53b266a4b968ea9e8d73702976021558 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Tue, 30 Sep 2025 12:52:26 +0200 Subject: [PATCH 21/33] try skip this chart --- nix/scripts/list-helm-containers.sh | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/nix/scripts/list-helm-containers.sh b/nix/scripts/list-helm-containers.sh index e1d81b70d..ddc5bfe35 100755 --- a/nix/scripts/list-helm-containers.sh +++ b/nix/scripts/list-helm-containers.sh @@ -76,13 +76,21 @@ images="" # render the charts, and assemble the list of images this would fetch. while IFS= read -r chart; do echo "Running helm template on chart ${chart}โ€ฆ" >&2 - # Extract raw images before replacement - raw_images=$(helm template --debug "${chart}" \ - --set federate.dtls.tls.key=emptyString \ - --set federate.dtls.tls.crt=emptyString \ - $( [[ -f "${VALUES_DIR}"/$(basename "${chart}")/"${VALUES_TYPE}"-values.example.yaml ]] && echo "-f ${VALUES_DIR}/$(basename "${chart}")/${VALUES_TYPE}-values.example.yaml" ) \ - $( [[ -f "${VALUES_DIR}"/$(basename "${chart}")/"${VALUES_TYPE}"-secrets.example.yaml ]] && echo "-f ${VALUES_DIR}/$(basename "${chart}")/${VALUES_TYPE}-secrets.example.yaml" ) \ - | yq -r '..|.image?' | grep -v "^null$" | grep -v "^---$" | grep -v "^$") + # Extract raw images before replacement with timeout and error handling + # Use a subshell with timeout mechanism + raw_images=$( + ( + helm template --debug "${chart}" \ + --set federate.dtls.tls.key=emptyString \ + --set federate.dtls.tls.crt=emptyString \ + $( [[ -f "${VALUES_DIR}"/$(basename "${chart}")/"${VALUES_TYPE}"-values.example.yaml ]] && echo "-f ${VALUES_DIR}/$(basename "${chart}")/${VALUES_TYPE}-values.example.yaml" ) \ + $( [[ -f "${VALUES_DIR}"/$(basename "${chart}")/"${VALUES_TYPE}"-secrets.example.yaml ]] && echo "-f ${VALUES_DIR}/$(basename "${chart}")/${VALUES_TYPE}-secrets.example.yaml" ) \ + 2>/dev/null | yq -r '..|.image?' | grep -v "^null$" | grep -v "^---$" | grep -v "^$" + ) || { + echo "WARNING: Failed to process chart $(basename $chart), skipping..." >&2 + echo "" + } + ) # Check for bitnami images before replacement if echo "$raw_images" | grep -q "^bitnami/"; then From 4f80a1a5d2ec8aac2ad49a2ad42f32cb38fb606a Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Tue, 30 Sep 2025 14:08:52 +0200 Subject: [PATCH 22/33] fix grep no match issue --- nix/scripts/list-helm-containers.sh | 31 +++++++++++++++-------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/nix/scripts/list-helm-containers.sh b/nix/scripts/list-helm-containers.sh index ddc5bfe35..f55e28799 100755 --- a/nix/scripts/list-helm-containers.sh +++ b/nix/scripts/list-helm-containers.sh @@ -76,21 +76,22 @@ images="" # render the charts, and assemble the list of images this would fetch. while IFS= read -r chart; do echo "Running helm template on chart ${chart}โ€ฆ" >&2 - # Extract raw images before replacement with timeout and error handling - # Use a subshell with timeout mechanism - raw_images=$( - ( - helm template --debug "${chart}" \ - --set federate.dtls.tls.key=emptyString \ - --set federate.dtls.tls.crt=emptyString \ - $( [[ -f "${VALUES_DIR}"/$(basename "${chart}")/"${VALUES_TYPE}"-values.example.yaml ]] && echo "-f ${VALUES_DIR}/$(basename "${chart}")/${VALUES_TYPE}-values.example.yaml" ) \ - $( [[ -f "${VALUES_DIR}"/$(basename "${chart}")/"${VALUES_TYPE}"-secrets.example.yaml ]] && echo "-f ${VALUES_DIR}/$(basename "${chart}")/${VALUES_TYPE}-secrets.example.yaml" ) \ - 2>/dev/null | yq -r '..|.image?' | grep -v "^null$" | grep -v "^---$" | grep -v "^$" - ) || { - echo "WARNING: Failed to process chart $(basename $chart), skipping..." >&2 - echo "" - } - ) + # Extract raw images before replacement with error handling + set +e # Temporarily disable exit on error + raw_images=$(helm template --debug "${chart}" \ + --set federate.dtls.tls.key=emptyString \ + --set federate.dtls.tls.crt=emptyString \ + $( [[ -f "${VALUES_DIR}"/$(basename "${chart}")/"${VALUES_TYPE}"-values.example.yaml ]] && echo "-f ${VALUES_DIR}/$(basename "${chart}")/${VALUES_TYPE}-values.example.yaml" ) \ + $( [[ -f "${VALUES_DIR}"/$(basename "${chart}")/"${VALUES_TYPE}"-secrets.example.yaml ]] && echo "-f ${VALUES_DIR}/$(basename "${chart}")/${VALUES_TYPE}-secrets.example.yaml" ) \ + 2>/dev/null | yq -r '..|.image?' | grep -v "^null$" | grep -v "^---$" | grep -v "^$" 2>/dev/null || true) + + helm_exit_code=$? + set -e # Re-enable exit on error + + if [[ $helm_exit_code -ne 0 ]]; then + echo "WARNING: Failed to process chart $(basename $chart), skipping..." >&2 + raw_images="" + fi # Check for bitnami images before replacement if echo "$raw_images" | grep -q "^bitnami/"; then From e43b40d26555961cfae4ac13270a794195ad1a29 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Tue, 30 Sep 2025 15:19:43 +0200 Subject: [PATCH 23/33] try another fix to append images correctly --- nix/scripts/list-helm-containers.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/scripts/list-helm-containers.sh b/nix/scripts/list-helm-containers.sh index f55e28799..d61b2ca40 100755 --- a/nix/scripts/list-helm-containers.sh +++ b/nix/scripts/list-helm-containers.sh @@ -109,4 +109,4 @@ while IFS= read -r chart; do append_chart_entry "$(basename $chart)" "$image_array" "${HELM_IMAGE_TREE_FILE}" fi done -echo -e "$images" | grep . | sort -u +echo -e "$images" | grep . | sort -u || true From 893a080d891d4f1c51a7aa499e24c6d8e8ef2dce Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Tue, 30 Sep 2025 15:56:19 +0200 Subject: [PATCH 24/33] try with aws-ingress issue --- nix/scripts/list-helm-containers.sh | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/nix/scripts/list-helm-containers.sh b/nix/scripts/list-helm-containers.sh index d61b2ca40..c11fb6d4b 100755 --- a/nix/scripts/list-helm-containers.sh +++ b/nix/scripts/list-helm-containers.sh @@ -78,11 +78,28 @@ while IFS= read -r chart; do echo "Running helm template on chart ${chart}โ€ฆ" >&2 # Extract raw images before replacement with error handling set +e # Temporarily disable exit on error + # Determine values file to use (prod first, then demo as fallback) + values_file="" + if [[ -f "${VALUES_DIR}"/$(basename "${chart}")/"${VALUES_TYPE}"-values.example.yaml ]]; then + values_file="${VALUES_DIR}/$(basename "${chart}")/${VALUES_TYPE}-values.example.yaml" + elif [[ -f "${VALUES_DIR}"/$(basename "${chart}")/demo-values.example.yaml ]]; then + values_file="${VALUES_DIR}/$(basename "${chart}")/demo-values.example.yaml" + echo "DEBUG: Using demo values for $(basename $chart) (no ${VALUES_TYPE} values found)" >&2 + fi + + # Determine secrets file to use + secrets_file="" + if [[ -f "${VALUES_DIR}"/$(basename "${chart}")/"${VALUES_TYPE}"-secrets.example.yaml ]]; then + secrets_file="${VALUES_DIR}/$(basename "${chart}")/${VALUES_TYPE}-secrets.example.yaml" + elif [[ -f "${VALUES_DIR}"/$(basename "${chart}")/demo-secrets.example.yaml ]]; then + secrets_file="${VALUES_DIR}/$(basename "${chart}")/demo-secrets.example.yaml" + fi + raw_images=$(helm template --debug "${chart}" \ --set federate.dtls.tls.key=emptyString \ --set federate.dtls.tls.crt=emptyString \ - $( [[ -f "${VALUES_DIR}"/$(basename "${chart}")/"${VALUES_TYPE}"-values.example.yaml ]] && echo "-f ${VALUES_DIR}/$(basename "${chart}")/${VALUES_TYPE}-values.example.yaml" ) \ - $( [[ -f "${VALUES_DIR}"/$(basename "${chart}")/"${VALUES_TYPE}"-secrets.example.yaml ]] && echo "-f ${VALUES_DIR}/$(basename "${chart}")/${VALUES_TYPE}-secrets.example.yaml" ) \ + $( [[ -n "$values_file" ]] && echo "-f $values_file" ) \ + $( [[ -n "$secrets_file" ]] && echo "-f $secrets_file" ) \ 2>/dev/null | yq -r '..|.image?' | grep -v "^null$" | grep -v "^---$" | grep -v "^$" 2>/dev/null || true) helm_exit_code=$? From 7f0af76c8dda76270ba01444caf6c67b044879b9 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Tue, 30 Sep 2025 16:14:32 +0200 Subject: [PATCH 25/33] keep it simple --- nix/scripts/list-helm-containers.sh | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/nix/scripts/list-helm-containers.sh b/nix/scripts/list-helm-containers.sh index c11fb6d4b..f87242abe 100755 --- a/nix/scripts/list-helm-containers.sh +++ b/nix/scripts/list-helm-containers.sh @@ -5,7 +5,7 @@ # those. # In cases where no container image tag has been specified, it'll use `latest`. # The list is sorted and deduplicated, then printed to stdout. -set -eou pipefail +set -euo pipefail VALUES_DIR="" HELM_IMAGE_TREE_FILE="" @@ -57,17 +57,10 @@ append_chart_entry() { # of them, but only :latest in that case - it's bad enough there's no proper # versioning here. function optionally_complain() { + # Simply pass through all images - no validation needed + # The job is to replace bitnami, not validate image formats while IFS= read -r image; do - if [[ $image =~ ":latest" ]]; then - echo "Container $image with a latest tag found. Fix this chart. not compatible with offline. Components need explicit tags for that" >&2 - elif [[ $image =~ ":" ]]; then - echo "$image" - elif [[ $image =~ "@" ]]; then - echo "$image" - else - echo "Container $image without a tag found or pin found. Aborting! Fix this chart. not compatible with offline. Components need explicit tags for that" >&2 - exit 1 - fi + echo "$image" done } @@ -111,9 +104,9 @@ while IFS= read -r chart; do fi # Check for bitnami images before replacement - if echo "$raw_images" | grep -q "^bitnami/"; then + if echo "$raw_images" | grep -q "^bitnami/" 2>/dev/null; then echo "DEBUG: Found bitnami images in chart $(basename $chart):" >&2 - echo "$raw_images" | grep "^bitnami/" >&2 + echo "$raw_images" | grep "^bitnami/" >&2 || true fi # Apply sed replacement and other processing From affac23bdd75016e6e286473e27df0462cb30cdc Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Tue, 30 Sep 2025 16:30:19 +0200 Subject: [PATCH 26/33] try fix the count --- nix/scripts/list-helm-containers.sh | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/nix/scripts/list-helm-containers.sh b/nix/scripts/list-helm-containers.sh index f87242abe..1ecaa242e 100755 --- a/nix/scripts/list-helm-containers.sh +++ b/nix/scripts/list-helm-containers.sh @@ -67,8 +67,10 @@ function optionally_complain() { images="" # For each helm chart passed in from stdin, use the example values to # render the charts, and assemble the list of images this would fetch. +chart_count=0 while IFS= read -r chart; do - echo "Running helm template on chart ${chart}โ€ฆ" >&2 + chart_count=$((chart_count + 1)) + echo "[$chart_count] Running helm template on chart ${chart}โ€ฆ" >&2 # Extract raw images before replacement with error handling set +e # Temporarily disable exit on error # Determine values file to use (prod first, then demo as fallback) @@ -77,7 +79,7 @@ while IFS= read -r chart; do values_file="${VALUES_DIR}/$(basename "${chart}")/${VALUES_TYPE}-values.example.yaml" elif [[ -f "${VALUES_DIR}"/$(basename "${chart}")/demo-values.example.yaml ]]; then values_file="${VALUES_DIR}/$(basename "${chart}")/demo-values.example.yaml" - echo "DEBUG: Using demo values for $(basename $chart) (no ${VALUES_TYPE} values found)" >&2 + echo "Using demo values for $(basename $chart) (no ${VALUES_TYPE} values found)" >&2 fi # Determine secrets file to use @@ -110,7 +112,11 @@ while IFS= read -r chart; do fi # Apply sed replacement and other processing - current_images=$(echo "$raw_images" | sed -e 's|^bitnami/|bitnamilegacy/|g' -e 's|^docker\.io/bitnami/|docker.io/bitnamilegacy/|g' | grep -v "^$" | optionally_complain | sort -u) + if [[ -n "$raw_images" ]]; then + current_images=$(echo "$raw_images" | sed -e 's|^bitnami/|bitnamilegacy/|g' -e 's|^docker\.io/bitnami/|docker.io/bitnamilegacy/|g' | grep -v "^$" | optionally_complain | sort -u) + else + current_images="" + fi images+="$current_images\n" if [[ -n "$current_images" ]]; then From f41740500fb2c9998e2381d2f41fd497f83b9f15 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Wed, 1 Oct 2025 09:55:53 +0200 Subject: [PATCH 27/33] fix jq issue --- offline/cd-with-retry.sh | 2 +- offline/cd.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/offline/cd-with-retry.sh b/offline/cd-with-retry.sh index 86cb7d113..ba3407276 100755 --- a/offline/cd-with-retry.sh +++ b/offline/cd-with-retry.sh @@ -136,7 +136,7 @@ eval "$(ssh-agent)" ssh-add - <<< "$ssh_private_key" terraform output -json static-inventory > inventory.json -yq eval -P '.' inventory.json > inventory.yml +yq eval '.' inventory.json > inventory.yml ssh -oStrictHostKeyChecking=accept-new -oConnectionAttempts=10 "root@$adminhost" tar xzv < "$ARTIFACTS_DIR/assets.tgz" diff --git a/offline/cd.sh b/offline/cd.sh index 5a471afc9..afae7a456 100755 --- a/offline/cd.sh +++ b/offline/cd.sh @@ -24,7 +24,7 @@ eval `ssh-agent` ssh-add - <<< "$ssh_private_key" terraform output -json static-inventory > inventory.json -yq eval -P '.' inventory.json > inventory.yml +yq eval '.' inventory.json > inventory.yml ssh -oStrictHostKeyChecking=accept-new -oConnectionAttempts=10 "root@$adminhost" tar xzv < "$ARTIFACTS_DIR/assets.tgz" From 7f2a1afb9fd75072cac834872b22bb1ca2604d45 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Wed, 1 Oct 2025 10:58:42 +0200 Subject: [PATCH 28/33] use yq --- offline/cd-with-retry.sh | 2 +- offline/cd.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/offline/cd-with-retry.sh b/offline/cd-with-retry.sh index ba3407276..aa2d5a666 100755 --- a/offline/cd-with-retry.sh +++ b/offline/cd-with-retry.sh @@ -136,7 +136,7 @@ eval "$(ssh-agent)" ssh-add - <<< "$ssh_private_key" terraform output -json static-inventory > inventory.json -yq eval '.' inventory.json > inventory.yml +yq -y '.' inventory.json > inventory.yml ssh -oStrictHostKeyChecking=accept-new -oConnectionAttempts=10 "root@$adminhost" tar xzv < "$ARTIFACTS_DIR/assets.tgz" diff --git a/offline/cd.sh b/offline/cd.sh index afae7a456..53038b865 100755 --- a/offline/cd.sh +++ b/offline/cd.sh @@ -24,7 +24,7 @@ eval `ssh-agent` ssh-add - <<< "$ssh_private_key" terraform output -json static-inventory > inventory.json -yq eval '.' inventory.json > inventory.yml +yq -y '.' inventory.json > inventory.yml ssh -oStrictHostKeyChecking=accept-new -oConnectionAttempts=10 "root@$adminhost" tar xzv < "$ARTIFACTS_DIR/assets.tgz" From fdcb7d550b8b4f63ddc11285b09eb90103065884 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Wed, 1 Oct 2025 14:23:17 +0200 Subject: [PATCH 29/33] fix: patch chart images --- offline/tasks/patch-chart-images.sh | 106 ++++++++++++++++++++++++++++ offline/tasks/proc_pull_charts.sh | 10 +++ 2 files changed, 116 insertions(+) create mode 100755 offline/tasks/patch-chart-images.sh diff --git a/offline/tasks/patch-chart-images.sh b/offline/tasks/patch-chart-images.sh new file mode 100755 index 000000000..de45a92d6 --- /dev/null +++ b/offline/tasks/patch-chart-images.sh @@ -0,0 +1,106 @@ +#!/usr/bin/env bash +# Script to patch bitnami repository references in chart files + +set -euo pipefail + +CHARTS_DIR="${1:-}" + +if [[ -z "$CHARTS_DIR" ]]; then + echo "Usage: $0 " + echo "Example: $0 ./output/charts" + exit 1 +fi + +echo "Patching bitnami repository references in: $CHARTS_DIR" + +patched_count=0 +file_count=0 + +# Function to patch a single file +patch_file() { + local file="$1" + local temp_file=$(mktemp) + local chart_name="" + + # Extract chart name from file path for logging + if [[ "$file" =~ /charts/([^/]+)/ ]]; then + chart_name="${BASH_REMATCH[1]}" + else + chart_name="unknown" + fi + + # Apply sed replacements for various image reference patterns + sed -e 's|repository: bitnami/|repository: bitnamilegacy/|g' \ + -e 's|repository: docker\.io/bitnami/|repository: docker.io/bitnamilegacy/|g' \ + -e 's|image: bitnami/|image: bitnamilegacy/|g' \ + -e 's|image: docker\.io/bitnami/|image: docker.io/bitnamilegacy/|g' \ + -e 's|: bitnami/|: bitnamilegacy/|g' \ + -e 's|: docker\.io/bitnami/|: docker.io/bitnamilegacy/|g' \ + "$file" > "$temp_file" + + # Check if file was modified and log specific changes + if ! cmp -s "$file" "$temp_file"; then + # Show what was changed + echo " โœ… Patched chart: $chart_name" + echo " File: $(basename "$file")" + + # Extract and log the specific bitnami references that were changed + local changes=$(diff "$file" "$temp_file" 2>/dev/null | grep "^<\|^>" | grep -E "(bitnami|bitnamilegacy)" || true) + if [[ -n "$changes" ]]; then + echo " Changes:" + echo "$changes" | while read -r line; do + if [[ "$line" =~ ^\<.*bitnami/ ]]; then + local old_ref=$(echo "$line" | sed 's/^< *//' | grep -o 'bitnami/[^[:space:]]*' || echo "bitnami reference") + echo " - $old_ref โ†’ bitnamilegacy/${old_ref#bitnami/}" + fi + done + fi + + mv "$temp_file" "$file" + return 0 + else + rm "$temp_file" + return 1 + fi +} + +echo "Scanning and patching files..." + +# Process values.yaml files +while IFS= read -r -d '' file; do + file_count=$((file_count + 1)) + if patch_file "$file"; then + patched_count=$((patched_count + 1)) + fi +done < <(find "$CHARTS_DIR" -name "values.yaml" -print0) + +# Process Chart.yaml files +while IFS= read -r -d '' file; do + file_count=$((file_count + 1)) + if patch_file "$file"; then + patched_count=$((patched_count + 1)) + fi +done < <(find "$CHARTS_DIR" -name "Chart.yaml" -print0) + +# Process template files (for direct image references) +while IFS= read -r -d '' file; do + file_count=$((file_count + 1)) + if patch_file "$file"; then + patched_count=$((patched_count + 1)) + fi +done < <(find "$CHARTS_DIR" -path "*/templates/*.yaml" -print0) + +echo +echo "=== Patching Summary ===" +echo "Files processed: $file_count" +echo "Files modified: $patched_count" + +if [[ $patched_count -gt 0 ]]; then + echo + echo "Charts with bitnami references successfully patched:" + # Extract unique chart names from the log output above + echo " (See detailed changes above for specific image references)" +else + echo "No bitnami image references found in any charts." +fi +echo "==========================" \ No newline at end of file diff --git a/offline/tasks/proc_pull_charts.sh b/offline/tasks/proc_pull_charts.sh index 353323c0a..c53bfe1fb 100755 --- a/offline/tasks/proc_pull_charts.sh +++ b/offline/tasks/proc_pull_charts.sh @@ -81,6 +81,16 @@ pull_charts() { (cd "${OUTPUT_DIR}"/charts; helm pull --version "$version" --untar "$repo_short_name/$name") done echo "Pulling charts done." + + # Patch bitnami repository references in pulled charts + echo "Patching bitnami repository references..." + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + PATCH_SCRIPT="${SCRIPT_DIR}/patch-chart-images.sh" + if [[ -f "$PATCH_SCRIPT" ]]; then + "$PATCH_SCRIPT" "${OUTPUT_DIR}/charts" + else + echo "Warning: patch-chart-images.sh not found at $PATCH_SCRIPT, skipping chart patching" + fi } wire_build="https://raw.githubusercontent.com/wireapp/wire-builds/91dc716636442af4131c37719d825ac08d36232a/build.json" From c933f6b580ce3fe4444b0dc6a4ecbe3f025c805b Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Wed, 1 Oct 2025 16:13:36 +0200 Subject: [PATCH 30/33] Update ephemeral database and redis values --- values/databases-ephemeral/demo-values.example.yaml | 2 +- values/databases-ephemeral/prod-values.example.yaml | 2 +- values/redis-ephemeral/prod-values.example.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/values/databases-ephemeral/demo-values.example.yaml b/values/databases-ephemeral/demo-values.example.yaml index b5f12ea08..be3b11820 100644 --- a/values/databases-ephemeral/demo-values.example.yaml +++ b/values/databases-ephemeral/demo-values.example.yaml @@ -8,7 +8,7 @@ redis-ephemeral: redis-ephemeral: image: registry: docker.io - repository: bitnami/redis + repository: bitnamilegacy/redis tag: 6.2.16 usePassword: false cluster: diff --git a/values/databases-ephemeral/prod-values.example.yaml b/values/databases-ephemeral/prod-values.example.yaml index 10d4f294d..578d66d4d 100644 --- a/values/databases-ephemeral/prod-values.example.yaml +++ b/values/databases-ephemeral/prod-values.example.yaml @@ -8,7 +8,7 @@ redis-ephemeral: redis-ephemeral: image: registry: docker.io - repository: bitnami/redis + repository: bitnamilegacy/redis tag: 6.2.16 usePassword: false cluster: diff --git a/values/redis-ephemeral/prod-values.example.yaml b/values/redis-ephemeral/prod-values.example.yaml index 65d1df801..1f268481f 100644 --- a/values/redis-ephemeral/prod-values.example.yaml +++ b/values/redis-ephemeral/prod-values.example.yaml @@ -1,7 +1,7 @@ redis-ephemeral: image: registry: docker.io - repository: bitnami/redis + repository: bitnamilegacy/redis tag: 6.2.16 usePassword: false cluster: From 9fbba20c90af9636bc413c12473cd8a545f1d319 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Thu, 2 Oct 2025 09:25:13 +0200 Subject: [PATCH 31/33] update offline workflow and scripts --- .github/workflows/offline.yml | 20 +++++++++------ nix/scripts/list-helm-containers.sh | 38 +++++++++++++++-------------- offline/tasks/proc_pull_charts.sh | 1 + 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/.github/workflows/offline.yml b/.github/workflows/offline.yml index f6fabfdb6..925296a94 100644 --- a/.github/workflows/offline.yml +++ b/.github/workflows/offline.yml @@ -80,7 +80,7 @@ jobs: # Deploy to Hetzner in parallel with S3 upload deploy-hetzner: - name: Deploy to Hetzner + name: Deploy default build to Hetzner if: "!contains(github.event.head_commit.message, 'skip ci')" needs: build-default runs-on: @@ -145,7 +145,6 @@ jobs: build-demo: name: Build demo profile if: "!contains(github.event.head_commit.message, 'skip ci')" - needs: build-default runs-on: group: wire-server-deploy steps: @@ -161,6 +160,10 @@ jobs: - name: Install nix environment run: nix-env -f default.nix -iA env + - name: Get upload name + id: upload_name + run: echo "UPLOAD_NAME=$GITHUB_SHA" >> $GITHUB_OUTPUT + - name: Process the demo profile build run: ./offline/demo-build/build.sh env: @@ -169,8 +172,8 @@ jobs: - name: Copy demo build assets tarball to S3 run: | - aws s3 cp offline/demo-build/output/assets.tgz s3://public.wire.com/artifacts/wire-server-deploy-static-demo-${{ needs.build-default.outputs.upload_name }}.tgz - echo "Uploaded to: https://s3-$AWS_REGION.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-demo-${{ needs.build-default.outputs.upload_name }}.tgz" + aws s3 cp offline/demo-build/output/assets.tgz s3://public.wire.com/artifacts/wire-server-deploy-static-demo-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz + echo "Uploaded to: https://s3-$AWS_REGION.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-demo-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz" env: AWS_ACCESS_KEY_ID: '${{ secrets.AWS_ACCESS_KEY_ID }}' AWS_SECRET_ACCESS_KEY: '${{ secrets.AWS_SECRET_ACCESS_KEY }}' @@ -180,7 +183,6 @@ jobs: build-min: name: Build min profile if: "!contains(github.event.head_commit.message, 'skip ci')" - needs: build-default runs-on: group: wire-server-deploy steps: @@ -196,6 +198,10 @@ jobs: - name: Install nix environment run: nix-env -f default.nix -iA env + - name: Get upload name + id: upload_name + run: echo "UPLOAD_NAME=$GITHUB_SHA" >> $GITHUB_OUTPUT + - name: Process the min profile build run: ./offline/min-build/build.sh env: @@ -204,8 +210,8 @@ jobs: - name: Copy min build assets tarball to S3 run: | - aws s3 cp offline/min-build/output/assets.tgz s3://public.wire.com/artifacts/wire-server-deploy-static-min-${{ needs.build-default.outputs.upload_name }}.tgz - echo "Uploaded to: https://s3-$AWS_REGION.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-min-${{ needs.build-default.outputs.upload_name }}.tgz" + aws s3 cp offline/min-build/output/assets.tgz s3://public.wire.com/artifacts/wire-server-deploy-static-min-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz + echo "Uploaded to: https://s3-$AWS_REGION.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-min-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz" env: AWS_ACCESS_KEY_ID: '${{ secrets.AWS_ACCESS_KEY_ID }}' AWS_SECRET_ACCESS_KEY: '${{ secrets.AWS_SECRET_ACCESS_KEY }}' diff --git a/nix/scripts/list-helm-containers.sh b/nix/scripts/list-helm-containers.sh index 1ecaa242e..69a9dcf99 100755 --- a/nix/scripts/list-helm-containers.sh +++ b/nix/scripts/list-helm-containers.sh @@ -57,10 +57,17 @@ append_chart_entry() { # of them, but only :latest in that case - it's bad enough there's no proper # versioning here. function optionally_complain() { - # Simply pass through all images - no validation needed - # The job is to replace bitnami, not validate image formats while IFS= read -r image; do - echo "$image" + if [[ $image =~ ":latest" ]]; then + echo "Container $image with a latest tag found. Fix this chart. not compatible with offline. Components need explicit tags for that" >&2 + elif [[ $image =~ ":" ]]; then + echo "$image" + elif [[ $image =~ "@" ]]; then + echo "$image" + else + echo "Container $image without a tag found or pin found. Aborting! Fix this chart. not compatible with offline. Components need explicit tags for that" >&2 + exit 1 + fi done } @@ -71,7 +78,6 @@ chart_count=0 while IFS= read -r chart; do chart_count=$((chart_count + 1)) echo "[$chart_count] Running helm template on chart ${chart}โ€ฆ" >&2 - # Extract raw images before replacement with error handling set +e # Temporarily disable exit on error # Determine values file to use (prod first, then demo as fallback) values_file="" @@ -90,30 +96,26 @@ while IFS= read -r chart; do secrets_file="${VALUES_DIR}/$(basename "${chart}")/demo-secrets.example.yaml" fi - raw_images=$(helm template --debug "${chart}" \ - --set federate.dtls.tls.key=emptyString \ - --set federate.dtls.tls.crt=emptyString \ + raw_images=$(helm template "${chart}" \ $( [[ -n "$values_file" ]] && echo "-f $values_file" ) \ $( [[ -n "$secrets_file" ]] && echo "-f $secrets_file" ) \ - 2>/dev/null | yq -r '..|.image?' | grep -v "^null$" | grep -v "^---$" | grep -v "^$" 2>/dev/null || true) + 2>&1 | yq -r '..|.image?' | grep -v "^null$" | grep -v "^---$" | grep -v "^$" || true) helm_exit_code=$? set -e # Re-enable exit on error if [[ $helm_exit_code -ne 0 ]]; then - echo "WARNING: Failed to process chart $(basename $chart), skipping..." >&2 + echo "ERROR: Failed to process chart $(basename $chart)" >&2 + echo "Chart path: $chart" >&2 + echo "Values file: ${values_file:-none}" >&2 + echo "Secrets file: ${secrets_file:-none}" >&2 + echo "Try running: helm template $chart $([ -n "$values_file" ] && echo "-f $values_file") $([ -n "$secrets_file" ] && echo "-f $secrets_file")" >&2 raw_images="" fi - # Check for bitnami images before replacement - if echo "$raw_images" | grep -q "^bitnami/" 2>/dev/null; then - echo "DEBUG: Found bitnami images in chart $(basename $chart):" >&2 - echo "$raw_images" | grep "^bitnami/" >&2 || true - fi - - # Apply sed replacement and other processing + # Process extracted images if [[ -n "$raw_images" ]]; then - current_images=$(echo "$raw_images" | sed -e 's|^bitnami/|bitnamilegacy/|g' -e 's|^docker\.io/bitnami/|docker.io/bitnamilegacy/|g' | grep -v "^$" | optionally_complain | sort -u) + current_images=$(echo "$raw_images" | grep -v "^$" | optionally_complain | sort -u) else current_images="" fi @@ -125,4 +127,4 @@ while IFS= read -r chart; do append_chart_entry "$(basename $chart)" "$image_array" "${HELM_IMAGE_TREE_FILE}" fi done -echo -e "$images" | grep . | sort -u || true +echo -e "$images" | grep . | sort -u || true diff --git a/offline/tasks/proc_pull_charts.sh b/offline/tasks/proc_pull_charts.sh index c53bfe1fb..f20d942b8 100755 --- a/offline/tasks/proc_pull_charts.sh +++ b/offline/tasks/proc_pull_charts.sh @@ -83,6 +83,7 @@ pull_charts() { echo "Pulling charts done." # Patch bitnami repository references in pulled charts + # Remove the extraction and replacement when there will be no more bitnami charts echo "Patching bitnami repository references..." SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PATCH_SCRIPT="${SCRIPT_DIR}/patch-chart-images.sh" From 97cc27541c4e3bdb3eab56f61f8715df5a520f9e Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Thu, 2 Oct 2025 09:42:47 +0200 Subject: [PATCH 32/33] fix demo build --- values/postgresql/demo-values.example.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/values/postgresql/demo-values.example.yaml b/values/postgresql/demo-values.example.yaml index fcf671496..f0143ab6f 100644 --- a/values/postgresql/demo-values.example.yaml +++ b/values/postgresql/demo-values.example.yaml @@ -6,5 +6,5 @@ postgresql: enabled: false volumePermissions: image: - repository: bitnami/os-shell + repository: bitnamilegacy/os-shell tag: 12-debian-12-r46 From dba98b46743749e4400a63c180fc70469d8865e4 Mon Sep 17 00:00:00 2001 From: sghosh23 Date: Thu, 2 Oct 2025 10:02:06 +0200 Subject: [PATCH 33/33] fix lint and celanup --- .github/workflows/deploy-only.yml | 67 -------------- .github/workflows/offline.yml | 6 ++ .github/workflows/offline.yml.disabled | 123 ------------------------- offline/tasks/patch-chart-images.sh | 10 +- 4 files changed, 13 insertions(+), 193 deletions(-) delete mode 100644 .github/workflows/deploy-only.yml delete mode 100644 .github/workflows/offline.yml.disabled diff --git a/.github/workflows/deploy-only.yml b/.github/workflows/deploy-only.yml deleted file mode 100644 index caef2226c..000000000 --- a/.github/workflows/deploy-only.yml +++ /dev/null @@ -1,67 +0,0 @@ -name: Fast Deploy Only - -on: - workflow_dispatch: - inputs: - upload_name: - description: "Upload name (git SHA or tag)" - required: false - default: "" - issue_comment: - types: [created] - -jobs: - deploy-only: - name: Deploy existing build - if: | - github.event_name == 'workflow_dispatch' || - (github.event_name == 'issue_comment' && - github.event.issue.pull_request && - contains(github.event.comment.body, 'deploy-')) - runs-on: - group: wire-server-deploy - steps: - - uses: actions/checkout@v2 - with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} - submodules: true - - uses: cachix/install-nix-action@v27 - - uses: cachix/cachix-action@v15 - with: - name: wire-server - signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}" - - - name: Install nix environment - run: nix-env -f default.nix -iA env - - - name: Get upload name - id: upload_name - run: | - if [ -n "${{ github.event.inputs.upload_name }}" ]; then - echo "UPLOAD_NAME=${{ github.event.inputs.upload_name }}" >> $GITHUB_OUTPUT - elif [ "${{ github.event_name }}" = "issue_comment" ]; then - # Extract upload_name from comment like "deploy-a71cbf843a79907a9eaca72f46f9f64e8a0524d8" - COMMENT_BODY="${{ github.event.comment.body }}" - UPLOAD_NAME=$(echo "$COMMENT_BODY" | grep -o 'deploy-[a-zA-Z0-9_-]*' | head -1 | sed 's/deploy-//') - if [ -n "$UPLOAD_NAME" ]; then - echo "UPLOAD_NAME=$UPLOAD_NAME" >> $GITHUB_OUTPUT - echo "Extracted upload name from comment: $UPLOAD_NAME" - else - echo "UPLOAD_NAME=${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT - echo "No upload name found in comment, using PR head SHA" - fi - else - echo "UPLOAD_NAME=$GITHUB_SHA" >> $GITHUB_OUTPUT - fi - - - name: Install terraform - uses: hashicorp/setup-terraform@v3 - with: - terraform_version: "^1.3.7" - terraform_wrapper: false - - - name: Fast deploy to Hetzner - run: ./offline/cd-with-retry.sh - env: - HCLOUD_TOKEN: "${{ secrets.HCLOUD_TOKEN }}" - GITHUB_SHA: ${{ steps.upload_name.outputs.UPLOAD_NAME }} diff --git a/.github/workflows/offline.yml b/.github/workflows/offline.yml index 925296a94..80d78e178 100644 --- a/.github/workflows/offline.yml +++ b/.github/workflows/offline.yml @@ -179,6 +179,9 @@ jobs: AWS_SECRET_ACCESS_KEY: '${{ secrets.AWS_SECRET_ACCESS_KEY }}' AWS_REGION: "eu-west-1" + - name: Cleanup demo build assets + run: rm -rf offline/demo-build/output/ + # Build min profile build-min: name: Build min profile @@ -216,3 +219,6 @@ jobs: AWS_ACCESS_KEY_ID: '${{ secrets.AWS_ACCESS_KEY_ID }}' AWS_SECRET_ACCESS_KEY: '${{ secrets.AWS_SECRET_ACCESS_KEY }}' AWS_REGION: "eu-west-1" + + - name: Cleanup min build assets + run: rm -rf offline/min-build/output/ diff --git a/.github/workflows/offline.yml.disabled b/.github/workflows/offline.yml.disabled deleted file mode 100644 index 8654232a0..000000000 --- a/.github/workflows/offline.yml.disabled +++ /dev/null @@ -1,123 +0,0 @@ -on: - push: - branches: [master, develop] - tags: [ v* ] - paths-ignore: - - '*.md' - - '**/*.md' - pull_request: - branches: [master, develop] - paths-ignore: - - '*.md' - - '**/*.md' -jobs: - offline: - name: Prepare offline package - # Useful to skip expensive CI when writing docs - if: "!contains(github.event.head_commit.message, 'skip ci')" - runs-on: - group: wire-server-deploy - steps: - - uses: actions/checkout@v2 - with: - submodules: true - - uses: cachix/install-nix-action@v27 - - uses: cachix/cachix-action@v15 - with: - name: wire-server - signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}" - - - name: Install nix environment - run: nix-env -f default.nix -iA env - - - name: Get upload name - id: upload_name - run: | - # FIXME: Tag with a nice release name using the github tag... - # SOURCE_TAG=${GITHUB_REF#refs/tags/} - echo ::set-output name=UPLOAD_NAME::$GITHUB_SHA - # echo ::set-output name=UPLOAD_NAME::${SOURCE_TAG:-$GITHUB_SHA} - - # deafult profile build - - name: Process the default profile build - run: ./offline/default-build/build.sh - env: - GPG_PRIVATE_KEY: '${{ secrets.GPG_PRIVATE_KEY }}' - DOCKER_LOGIN: '${{ secrets.DOCKER_LOGIN }}' - - - name: Copy default build assets tarball to S3 and clean up - run: | - # Upload tarball for each profile by specifying their OUTPUT_TAR path - aws s3 cp offline/default-build/output/assets.tgz s3://public.wire.com/artifacts/wire-server-deploy-static-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz - echo "Uploaded to: https://s3-$AWS_REGION.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz" - # removing everything except assets.tgz as it is not required anymore in the further builds - find offline/default-build/output/ -mindepth 1 -maxdepth 1 ! -name 'assets.tgz' -exec rm -r {} + - env: - AWS_ACCESS_KEY_ID: '${{ secrets.AWS_ACCESS_KEY_ID }}' - AWS_SECRET_ACCESS_KEY: '${{ secrets.AWS_SECRET_ACCESS_KEY }}' - AWS_REGION: "eu-west-1" - - - name: Build and upload wire-server-deploy container - run: | - container_image=$(nix-build --no-out-link -A container) - skopeo copy --retry-times 10 --dest-creds "$DOCKER_LOGIN" \ - docker-archive:"$container_image" \ - "docker://quay.io/wire/wire-server-deploy:${{ steps.upload_name.outputs.UPLOAD_NAME }}" - env: - DOCKER_LOGIN: '${{ secrets.DOCKER_LOGIN }}' - - # demo profile build - - name: Process the demo profile build - run: ./offline/demo-build/build.sh - env: - GPG_PRIVATE_KEY: '${{ secrets.GPG_PRIVATE_KEY }}' - DOCKER_LOGIN: '${{ secrets.DOCKER_LOGIN }}' - - - name: Copy demo build assets tarball to S3 and clean up - run: | - # Upload tarball for each profile by specifying their OUTPUT_TAR path - aws s3 cp offline/demo-build/output/assets.tgz s3://public.wire.com/artifacts/wire-server-deploy-static-demo-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz - echo "Uploaded to: https://s3-$AWS_REGION.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-demo-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz" - # remove the assets from the build to optimize the space on the server - rm -rf offline/demo-build/output/* - env: - AWS_ACCESS_KEY_ID: '${{ secrets.AWS_ACCESS_KEY_ID }}' - AWS_SECRET_ACCESS_KEY: '${{ secrets.AWS_SECRET_ACCESS_KEY }}' - AWS_REGION: "eu-west-1" - - # min profile build - - name: Process the min profile build - run: ./offline/min-build/build.sh - env: - GPG_PRIVATE_KEY: '${{ secrets.GPG_PRIVATE_KEY }}' - DOCKER_LOGIN: '${{ secrets.DOCKER_LOGIN }}' - - - name: Copy min build assets tarball to S3 - run: | - # Upload tarball for each profile by specifying their OUTPUT_TAR path - aws s3 cp offline/min-build/output/assets.tgz s3://public.wire.com/artifacts/wire-server-deploy-static-min-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz - echo "Uploaded to: https://s3-$AWS_REGION.amazonaws.com/public.wire.com/artifacts/wire-server-deploy-static-min-${{ steps.upload_name.outputs.UPLOAD_NAME }}.tgz" - # remove the archives from the build to optimize the space on the server - rm -rf offline/min-build/output/* - env: - AWS_ACCESS_KEY_ID: '${{ secrets.AWS_ACCESS_KEY_ID }}' - AWS_SECRET_ACCESS_KEY: '${{ secrets.AWS_SECRET_ACCESS_KEY }}' - AWS_REGION: "eu-west-1" - - - name: Install terraform - uses: hashicorp/setup-terraform@v3 - with: - terraform_version: "^1.3.7" - terraform_wrapper: false - - - name: Deploy offline environment to hetzner with fast S3 deployment - run: | - ./offline/cd-with-retry-fast.sh - env: - HCLOUD_TOKEN: '${{ secrets.HCLOUD_TOKEN }}' - - #- name: Clean up hetzner environment; just in case - # if: always() - # run: (cd terraform/examples/wire-server-deploy-offline-hetzner ; terraform init && terraform destroy -auto-approve) - # env: - # HCLOUD_TOKEN: '${{ secrets.HCLOUD_TOKEN }}' diff --git a/offline/tasks/patch-chart-images.sh b/offline/tasks/patch-chart-images.sh index de45a92d6..175e05efd 100755 --- a/offline/tasks/patch-chart-images.sh +++ b/offline/tasks/patch-chart-images.sh @@ -19,9 +19,11 @@ file_count=0 # Function to patch a single file patch_file() { local file="$1" - local temp_file=$(mktemp) + local temp_file local chart_name="" + temp_file=$(mktemp) + # Extract chart name from file path for logging if [[ "$file" =~ /charts/([^/]+)/ ]]; then chart_name="${BASH_REMATCH[1]}" @@ -45,12 +47,14 @@ patch_file() { echo " File: $(basename "$file")" # Extract and log the specific bitnami references that were changed - local changes=$(diff "$file" "$temp_file" 2>/dev/null | grep "^<\|^>" | grep -E "(bitnami|bitnamilegacy)" || true) + local changes + changes=$(diff "$file" "$temp_file" 2>/dev/null | grep "^<\|^>" | grep -E "(bitnami|bitnamilegacy)" || true) if [[ -n "$changes" ]]; then echo " Changes:" echo "$changes" | while read -r line; do if [[ "$line" =~ ^\<.*bitnami/ ]]; then - local old_ref=$(echo "$line" | sed 's/^< *//' | grep -o 'bitnami/[^[:space:]]*' || echo "bitnami reference") + local old_ref + old_ref=$(echo "$line" | sed 's/^< *//' | grep -o 'bitnami/[^[:space:]]*' || echo "bitnami reference") echo " - $old_ref โ†’ bitnamilegacy/${old_ref#bitnami/}" fi done