-
-
Notifications
You must be signed in to change notification settings - Fork 13
Description
As it was reported on Drupal Slack, installing DDEV with this GitHub Action could lead to unexpectedly high (1-7 minutes) GitHub Action minutes consumption in random cases.
I think this problem is also visible on this project.
Proof:
- Run 1: Takes 47s
- Run 2: Takes 1m 25s
- Run 3: Takes 2m
- Billing Overview
The actual command execution completes in ~3 seconds, but GitHub Actions bills for 1-2 minutes due to infrastructure overhead from multiple shell process spawns.
RCA:
TL;DR sudo apt install command MUST BE avoid on GHA because that is a real time-consumer that randomly increases your billed hours.
Expected Impact:
- Billing reduction: 2 minutes → 1 minute (~50% cost reduction)
- Execution time: Reduced process overhead from 60-90s to 5-10s
- Reliability: Maintained backward compatibility and error handling
- Developer experience: No workflow changes required
Outdated RCA & Proposed solution
Root Cause Analysis:
The current main.js
implementation creates significant overhead through:
- 8 separate
execShellCommand()
calls - each spawning individual shell processes - Sequential execution pattern - preventing command optimization
- Process initialization overhead - 60-90 seconds of cumulative overhead across spawns
- Ubuntu runner variability - apt operations timing inconsistencies between 20s-2min
Proposed Solution: Optimize main.js execution pattern
Technique 1: Command Batching
Combine related shell operations to reduce process spawning from 8 to 3-5 executions:
// Batch repository setup and installation (5 commands → 1 execution)
const setupCommands = [
'sudo install -m 0755 -d /etc/apt/keyrings',
'curl -fsSL https://pkg.ddev.com/apt/gpg.key | gpg --dearmor | sudo tee /etc/apt/keyrings/ddev.gpg > /dev/null',
'sudo chmod a+r /etc/apt/keyrings/ddev.gpg',
'echo "deb [signed-by=/etc/apt/keyrings/ddev.gpg] https://pkg.ddev.com/apt/ * *" | sudo tee /etc/apt/sources.list.d/ddev.list >/dev/null',
`(sudo apt-get update || true) && sudo apt-get install -y ${ddevPackage} && mkcert -install`
];
yield execBatchCommands(setupCommands, "DDEV repository setup and installation");
Technique 2: Optimized Process Spawning
Replace individual shell spawns with batch execution using bash -c
:
function execBatchCommands(commands, description) {
return new Promise((resolve, reject) => {
const batchCmd = commands.join(' && ');
const process = child_process_1.spawn('bash', ['-c', batchCmd]);
// ... error handling
});
}
Technique 3: Strategic Error Isolation
Maintain separate executions only for operations requiring error isolation:
- Version hold operations (if version ≠ latest)
- Autostart with directory context
- Critical configuration steps