Skip to content
This repository was archived by the owner on Oct 10, 2025. It is now read-only.

Commit 49aa4f8

Browse files
committed
Merge #25: feat: [#24] Improve UX by adding automatic waiting to deployment commands
ad974e0 feat: [#24] improve UX by adding automatic waiting to deployment commands (Jose Celano) 826f054 docs: [#24] update copilot instructions with sudo cache management info (Jose Celano) Pull request description: ## Summary This PR resolves issue #24 by implementing automatic waiting logic in deployment commands to prevent premature execution failures and improve user experience. ## Problem Solved Previously, the three-step deployment workflow would fail if commands were run too quickly: ```bash make infra-apply ENVIRONMENT=local # Would succeed make app-deploy ENVIRONMENT=local # Would fail if run immediately make app-health-check ENVIRONMENT=local # Would fail due to services not ready ``` Users had to manually wait and guess timing, leading to poor UX and unreliable deployments. ## Solution Implemented **Solution 1**: Default automatic waiting with `SKIP_WAIT` option for advanced users. ### Key Features - ✅ **Automatic VM readiness waiting** in `make infra-apply` - ✅ **Automatic service health waiting** in `make app-deploy` - ✅ **SKIP_WAIT parameter** for advanced users (`SKIP_WAIT=true`) - ✅ **Clear progress feedback** during operations - ✅ **Bug fix**: Resolved OpenTofu working directory issues - ✅ **Comprehensive testing**: Manual + E2E validation ### Changes Made #### Infrastructure Layer - **shell-utils.sh**: Added `wait_for_vm_ip()` and `wait_for_cloud_init_completion()` functions - **provision-infrastructure.sh**: Automatic VM readiness waiting + bug fixes - **deploy-app.sh**: Enhanced service health waiting with better logging #### User Interface - **Makefile**: Added `SKIP_WAIT` parameter support for `infra-apply` and `app-deploy` - **Documentation**: Updated guides with new workflow and sudo cache management #### Testing & Quality - **test-e2e.sh**: Updated to use centralized waiting functions - **CI validation**: All tests pass, including comprehensive E2E testing ## Testing Results ### ✅ Manual Testing ```bash make infra-apply ENVIRONMENT=local # ✅ Waits for VM + cloud-init make app-deploy ENVIRONMENT=local # ✅ Waits for service health make app-health-check ENVIRONMENT=local # ✅ 100% success rate ``` ### ✅ E2E Testing - **Total test time**: 2m 40s - **Health checks**: 14/14 passed (100%) - **Smoke tests**: 0 failures - **Clean workflow**: Infrastructure → Application → Health → Cleanup ### ✅ Advanced User Workflow ```bash make infra-apply ENVIRONMENT=local SKIP_WAIT=true # ✅ Fast execution make app-deploy ENVIRONMENT=local SKIP_WAIT=true # ✅ No waiting ``` ## Impact ### 🎯 User Experience - **Eliminates manual timing guesswork** - **Provides clear progress feedback** - **Maintains advanced user flexibility** - **Fixes confusing warning messages** ### 🏗️ Technical Benefits - **Robust deployment workflow** - **Better error handling and logging** - **Centralized waiting logic** - **Improved twelve-factor compliance** ## Documentation Updated documentation includes: - **Contributor guide**: Sudo cache management, workflow improvements - **Cloud deployment guide**: Updated with new parameters - **Testing coverage**: Both manual and automated scenarios ## Breaking Changes **None** - This is a pure UX improvement that maintains backward compatibility. ## Related Issues - Closes #24 - Improves twelve-factor deployment workflow - Enhances contributor experience ## Review Notes - All CI tests pass ✅ - E2E testing validates complete workflow ✅ - Manual testing confirms UX improvements ✅ - Documentation updated ✅ - No breaking changes ✅ The three-step deployment workflow now works seamlessly without manual intervention, while preserving advanced user capabilities. ACKs for top commit: josecelano: ACK ad974e0 Tree-SHA512: 1995d568b3c742f7de91a85aeb8f43dc9cbd97910f681a13fb74978d19a925586805c2100e3f4cb64ec6be6a1121502c42a0cb0dc0919a2551f80d6cd6ae8b4e
2 parents d3e7ff9 + ad974e0 commit 49aa4f8

File tree

7 files changed

+262
-146
lines changed

7 files changed

+262
-146
lines changed

.github/copilot-instructions.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,9 +314,11 @@ The twelve-factor **Build, Release, Run** stages apply to the application deploy
314314

315315
#### Branch Naming
316316

317-
- **Format**: `{issue-number}-{short-description}`
318-
- **Examples**: `42-add-mysql-support`, `15-fix-ssl-renewal`
317+
- **Format**: `{issue-number}-{short-description-following-github-conventions}`
318+
- **GitHub conventions**: Use lowercase, separate words with hyphens, descriptive but concise
319+
- **Examples**: `42-add-mysql-support`, `15-fix-ssl-renewal`, `24-improve-ux-add-automatic-waiting-to-infra-apply-and-app-deploy-commands`
319320
- Always start with the GitHub issue number
321+
- Follow GitHub's recommended branch naming: lowercase, hyphens for word separation, descriptive of the change
320322

321323
#### Commit Messages
322324

Makefile

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,12 @@ infra-plan: ## Plan infrastructure changes
7171
infra-apply: ## Provision infrastructure (platform setup)
7272
@echo "Provisioning infrastructure for $(ENVIRONMENT)..."
7373
@echo "⚠️ This command may prompt for your password for sudo operations"
74-
$(SCRIPTS_DIR)/provision-infrastructure.sh $(ENVIRONMENT) apply
74+
@if [ "$(SKIP_WAIT)" = "true" ]; then \
75+
echo "⚠️ SKIP_WAIT=true - Infrastructure will not wait for full readiness"; \
76+
else \
77+
echo "ℹ️ Infrastructure will wait for full readiness (use SKIP_WAIT=true to skip)"; \
78+
fi
79+
SKIP_WAIT=$(SKIP_WAIT) $(SCRIPTS_DIR)/provision-infrastructure.sh $(ENVIRONMENT) apply
7580

7681
infra-destroy: ## Destroy infrastructure
7782
@echo "Destroying infrastructure for $(ENVIRONMENT)..."
@@ -116,7 +121,12 @@ infra-test-local: ## Run local-only infrastructure tests (requires virtualizatio
116121

117122
app-deploy: ## Deploy application (Twelve-Factor Build + Release + Run stages)
118123
@echo "Deploying application for $(ENVIRONMENT)..."
119-
$(SCRIPTS_DIR)/deploy-app.sh $(ENVIRONMENT)
124+
@if [ "$(SKIP_WAIT)" = "true" ]; then \
125+
echo "⚠️ SKIP_WAIT=true - Application will not wait for service readiness"; \
126+
else \
127+
echo "ℹ️ Application will wait for service readiness (use SKIP_WAIT=true to skip)"; \
128+
fi
129+
SKIP_WAIT=$(SKIP_WAIT) $(SCRIPTS_DIR)/deploy-app.sh $(ENVIRONMENT)
120130

121131
app-redeploy: ## Redeploy application without infrastructure changes
122132
@echo "Redeploying application for $(ENVIRONMENT)..."

docs/guides/cloud-deployment-guide.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,16 @@ make infra-config-local
6666

6767
```bash
6868
# Test deployment locally with KVM
69+
# Commands wait for full readiness by default
6970
make infra-apply ENVIRONMENT=local
7071
make app-deploy ENVIRONMENT=local
7172
make app-health-check
7273

74+
# Advanced users: Skip waiting for faster execution
75+
make infra-apply ENVIRONMENT=local SKIP_WAIT=true
76+
make app-deploy ENVIRONMENT=local SKIP_WAIT=true
77+
make app-health-check
78+
7379
# Access the local instance via SSH
7480
make vm-ssh
7581

@@ -247,6 +253,41 @@ should be tested in a staging environment first.
247253

248254
## Detailed Deployment Process
249255

256+
### ✅ Improved User Experience (Automatic Waiting)
257+
258+
**Issue #24 - Enhanced Workflow**: The deployment commands now wait for full readiness by
259+
default, providing a much better user experience:
260+
261+
**Previous workflow problems**:
262+
263+
- Commands completed before systems were actually ready
264+
- Users had to manually wait between steps without clear indicators
265+
- Following commands often failed if run too quickly
266+
267+
**✅ Current improved workflow**:
268+
269+
```bash
270+
# Each command waits for full readiness by default
271+
make infra-apply ENVIRONMENT=local # Waits for VM IP + cloud-init completion
272+
make app-deploy ENVIRONMENT=local # Waits for all services to be healthy
273+
make app-health-check # Validates everything is working
274+
```
275+
276+
**Key improvements**:
277+
278+
-**Clear progress indicators**: You see exactly what's happening during waits
279+
-**Automatic readiness detection**: Commands complete when actually ready for next step
280+
-**Reliable workflow**: No more timing-related failures between commands
281+
-**Backwards compatibility**: Use `SKIP_WAIT=true` for original fast behavior
282+
283+
**Advanced usage** (for CI/automation):
284+
285+
```bash
286+
# Skip waiting for faster execution (original behavior)
287+
make infra-apply ENVIRONMENT=local SKIP_WAIT=true
288+
make app-deploy ENVIRONMENT=local SKIP_WAIT=true
289+
```
290+
250291
### Infrastructure Deployment
251292

252293
The infrastructure deployment creates and configures the VM:
@@ -262,6 +303,8 @@ make infra-apply ENVIRONMENT=production
262303
# 4. Sets up torrust user with SSH access
263304
# 5. Configures firewall rules
264305
# 6. Creates persistent data volume
306+
# 7. ✅ NEW: Waits for VM IP assignment and cloud-init completion
307+
# 8. ✅ NEW: Ensures infrastructure is ready for next step
265308
```
266309

267310
### Application Deployment
@@ -284,6 +327,8 @@ make app-deploy ENVIRONMENT=production
284327
# - Grafana dashboards
285328
# 5. Configures automated maintenance tasks
286329
# 6. Validates all service health
330+
# 7. ✅ NEW: Waits for all services to be healthy and ready
331+
# 8. ✅ NEW: Ensures deployment is complete before finishing
287332
```
288333

289334
### Health Validation

infrastructure/scripts/deploy-app.sh

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ TERRAFORM_DIR="${PROJECT_ROOT}/infrastructure/terraform"
1414
ENVIRONMENT="${1:-local}"
1515
VM_IP="${2:-}"
1616
SKIP_HEALTH_CHECK="${SKIP_HEALTH_CHECK:-false}"
17+
SKIP_WAIT="${SKIP_WAIT:-false}" # New parameter for skipping waiting
1718
ENABLE_HTTPS="${ENABLE_SSL:-true}" # Enable HTTPS with self-signed certificates by default
1819

1920
# Source shared shell utilities
@@ -707,23 +708,27 @@ wait_for_services() {
707708
setup_backup_automation() {
708709
local vm_ip="$1"
709710

711+
log_info " Checking backup automation configuration..."
712+
710713
# Load environment variables from the generated .env file
711714
if [[ -f "${PROJECT_ROOT}/application/storage/compose/.env" ]]; then
712715
# shellcheck source=/dev/null
713716
source "${PROJECT_ROOT}/application/storage/compose/.env"
717+
log_info " ✅ Loaded environment configuration"
714718
else
715-
log_warning "Environment file not found, using defaults"
719+
log_warning " ⚠️ Environment file not found, using defaults"
716720
fi
717721

718722
# Check if backup automation is enabled
719723
if [[ "${ENABLE_DB_BACKUPS:-false}" != "true" ]]; then
720-
log_info "Database backup automation disabled (ENABLE_DB_BACKUPS=false)"
724+
log_info " ⏹️ Database backup automation disabled (ENABLE_DB_BACKUPS=${ENABLE_DB_BACKUPS:-false})"
721725
return 0
722726
fi
723727

724-
log_info "Setting up automated database backups..."
728+
log_info " ✅ Database backup automation enabled - proceeding with setup..."
725729

726730
# Create backup directory and set permissions
731+
log_info " ⏳ Creating backup directory and setting permissions..."
727732
vm_exec "${vm_ip}" "
728733
# Create backup directory if it doesn't exist
729734
sudo mkdir -p /var/lib/torrust/mysql/backups
@@ -734,8 +739,10 @@ setup_backup_automation() {
734739
# Set appropriate permissions
735740
chmod 755 /var/lib/torrust/mysql/backups
736741
" "Setting up backup directory"
742+
log_info " ✅ Backup directory setup completed"
737743

738744
# Install crontab entry for automated backups
745+
log_info " ⏳ Installing MySQL backup cron job..."
739746
vm_exec "${vm_ip}" "
740747
cd /home/torrust/github/torrust/torrust-tracker-demo
741748
@@ -752,8 +759,10 @@ setup_backup_automation() {
752759
echo 'Current crontab entries:'
753760
crontab -l || echo 'No crontab entries found'
754761
" "Installing MySQL backup cron job"
762+
log_info " ✅ Cron job installation completed"
755763

756764
# Test backup script functionality
765+
log_info " ⏳ Validating backup script functionality..."
757766
vm_exec "${vm_ip}" "
758767
cd /home/torrust/github/torrust/torrust-tracker-demo/application
759768
@@ -775,8 +784,9 @@ setup_backup_automation() {
775784
echo '✅ Fixed backup script permissions'
776785
fi
777786
" "Validating backup script"
787+
log_info " ✅ Backup script validation completed"
778788

779-
log_success "Database backup automation configured successfully"
789+
log_success " 🎉 Database backup automation configured successfully"
780790
log_info "Backup schedule: Daily at 3:00 AM"
781791
log_info "Backup location: /var/lib/torrust/mysql/backups"
782792
log_info "Retention period: ${BACKUP_RETENTION_DAYS:-7} days"
@@ -817,19 +827,32 @@ run_stage() {
817827
docker compose --env-file /var/lib/torrust/compose/.env up -d
818828
" "Starting application services"
819829

820-
# Wait for services to initialize
821-
wait_for_services "${vm_ip}"
830+
# Wait for services to initialize (unless skipped)
831+
if [[ "${SKIP_WAIT}" != "true" ]]; then
832+
log_info "⏳ Waiting for application services to be healthy..."
833+
log_info " (Use SKIP_WAIT=true to skip this waiting)"
834+
wait_for_services "${vm_ip}"
835+
log_success "🎉 All application services are healthy and ready!"
836+
else
837+
log_warning "⚠️ Skipping wait for service health checks (SKIP_WAIT=true)"
838+
log_info " Note: Services may not be ready immediately"
839+
fi
822840

823841
# Setup HTTPS with self-signed certificates (if enabled)
824842
if [[ "${ENABLE_HTTPS}" == "true" ]]; then
843+
log_info "⏳ Setting up HTTPS certificates..."
825844
log_info "HTTPS certificates already generated - services should be running with HTTPS..."
826-
log_success "HTTPS setup completed"
845+
log_success "✅ HTTPS setup completed"
846+
else
847+
log_info "⏹️ HTTPS setup skipped (ENABLE_HTTPS=${ENABLE_HTTPS})"
827848
fi
828849

829850
# Setup database backup automation (if enabled)
851+
log_info "⏳ Setting up database backup automation..."
830852
setup_backup_automation "${vm_ip}"
853+
log_success "✅ Database backup automation completed"
831854

832-
log_success "Run stage completed"
855+
log_success "🎉 Run stage completed successfully"
833856
}
834857

835858
# Validate deployment (Health checks)
@@ -1018,10 +1041,14 @@ main() {
10181041
test_ssh_connection "${vm_ip}"
10191042
wait_for_system_ready "${vm_ip}"
10201043
release_stage "${vm_ip}"
1021-
run_stage "${vm_ip}"
1044+
run_stage "${vm_ip}" # This already includes waiting for services
10221045

10231046
if [[ "${SKIP_HEALTH_CHECK}" != "true" ]]; then
1047+
log_info "⏳ Running deployment validation..."
10241048
validate_deployment "${vm_ip}"
1049+
log_success "✅ Deployment validation completed"
1050+
else
1051+
log_warning "⚠️ Skipping deployment validation (SKIP_HEALTH_CHECK=true)"
10251052
fi
10261053

10271054
show_connection_info "${vm_ip}"
@@ -1040,6 +1067,7 @@ Arguments:
10401067
10411068
Environment Variables:
10421069
SKIP_HEALTH_CHECK Skip health check validation (true/false, default: false)
1070+
SKIP_WAIT Skip waiting for services to be ready (true/false, default: false)
10431071
10441072
Examples:
10451073
$0 local # Deploy to local environment (get IP from Terraform)

infrastructure/scripts/provision-infrastructure.sh

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@ PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
1111
TERRAFORM_DIR="${PROJECT_ROOT}/infrastructure/terraform"
1212

1313
# Default values
14-
# Configuration
15-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
16-
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
1714
ENVIRONMENT="${1:-local}"
1815
ACTION="${2:-apply}"
16+
SKIP_WAIT="${SKIP_WAIT:-false}" # New parameter for skipping waiting
17+
SKIP_WAIT="${SKIP_WAIT:-false}" # New parameter for skipping waiting
1918

2019
# Source shared shell utilities
2120
# shellcheck source=../../scripts/shell-utils.sh
@@ -115,9 +114,32 @@ provision_infrastructure() {
115114

116115
tofu apply -auto-approve -var-file="local.tfvars"
117116

117+
# Wait for infrastructure to be fully ready (unless skipped)
118+
if [[ "${SKIP_WAIT}" != "true" ]]; then
119+
log_info "⏳ Waiting for infrastructure to be fully ready..."
120+
log_info " (Use SKIP_WAIT=true to skip this waiting)"
121+
122+
# Wait for VM IP assignment
123+
if ! wait_for_vm_ip "${ENVIRONMENT}" "${PROJECT_ROOT}"; then
124+
log_error "Failed to wait for VM IP assignment"
125+
exit 1
126+
fi
127+
128+
# Wait for cloud-init completion
129+
if ! wait_for_cloud_init_completion "${ENVIRONMENT}"; then
130+
log_error "Failed to wait for cloud-init completion"
131+
exit 1
132+
fi
133+
134+
log_success "🎉 Infrastructure is fully ready for application deployment!"
135+
else
136+
log_warning "⚠️ Skipping wait for infrastructure readiness (SKIP_WAIT=true)"
137+
log_info " Note: You may need to wait before running app-deploy"
138+
fi
139+
118140
# Get VM IP and display connection info
119141
local vm_ip
120-
vm_ip=$(tofu output -raw vm_ip 2>/dev/null || echo "")
142+
vm_ip=$(cd "${TERRAFORM_DIR}" && tofu output -raw vm_ip 2>/dev/null || echo "")
121143

122144
if [[ -n "${vm_ip}" ]]; then
123145
log_success "Infrastructure provisioned successfully"

0 commit comments

Comments
 (0)