-
Notifications
You must be signed in to change notification settings - Fork 2.3k
ci(workflows): harden linux-gcc-cmake-odbc apt/dpkg installs with retries and diagnostics #5072
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…gnostic log upload for linux-gcc-cmake-odbc Co-authored-by: aleks-f <[email protected]>
|
@copilot that change passed in this PR, but is failing again in main and other branches |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR hardens the linux-gcc-cmake-odbc GitHub Actions workflow to address intermittent failures during apt/dpkg package installation steps. The changes make all package operations non-interactive, add retry logic for transient failures, fix dependency resolution issues, and capture diagnostic logs for troubleshooting.
Key Changes:
- Made all apt/dpkg operations non-interactive using
DEBIAN_FRONTEND=noninteractiveand dpkg configuration options - Added 3-attempt retry loop for apt-get install with 10-second backoff between attempts
- Implemented comprehensive failure diagnostics with automatic artifact upload for post-mortem analysis
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| sudo dpkg -i devartodbcoracle_amd64.deb | ||
| - run: ls -l /etc/apt/sources.list.d/ | ||
| - name: Setup SQL Server ODBC connector | ||
| sudo dpkg -i devartodbcoracle_amd64.deb || true |
Copilot
AI
Dec 6, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Oracle ODBC dpkg command should also have explicit configuration options to avoid interactive prompts, similar to the Microsoft packages step. While || true allows it to fail, adding dpkg options would make the non-interactive intent clearer and match the hardening approach:
sudo DEBIAN_FRONTEND=noninteractive dpkg -i --force-confdef --force-confold devartodbcoracle_amd64.deb || trueThis ensures dpkg won't prompt for configuration file conflicts.
| sudo dpkg -i devartodbcoracle_amd64.deb || true | |
| sudo dpkg -i --force-confdef --force-confold devartodbcoracle_amd64.deb || true |
| DEBIAN_FRONTEND: noninteractive | ||
| run: | | ||
| set -euxo pipefail | ||
| wget https://www.devart.com/odbc/oracle/devartodbcoracle_amd64.deb |
Copilot
AI
Dec 6, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The wget command lacks retry logic and timeout configuration, which could fail due to transient network issues. Given the PR's goal of hardening against transient failures, consider adding retry and timeout options:
wget --tries=3 --timeout=30 https://www.devart.com/odbc/oracle/devartodbcoracle_amd64.debThis aligns with the retry philosophy applied to apt-get operations throughout the PR.
| wget https://www.devart.com/odbc/oracle/devartodbcoracle_amd64.deb | |
| wget --tries=3 --timeout=30 https://www.devart.com/odbc/oracle/devartodbcoracle_amd64.deb |
| DEBIAN_FRONTEND: noninteractive | ||
| run: | | ||
| set -euxo pipefail | ||
| curl -sSL -O https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb |
Copilot
AI
Dec 6, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The curl command lacks retry logic and timeout configuration. Given the PR's goal of hardening against transient failures, consider adding retry options:
curl --retry 3 --retry-delay 5 --max-time 60 -sSL -O https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.debThis aligns with the retry philosophy applied to apt-get operations throughout the PR.
| curl -sSL -O https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb | |
| curl --retry 3 --retry-delay 5 --max-time 60 -sSL -O https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb |
| - name: Capture apt/dpkg/system diagnostics on failure | ||
| if: failure() | ||
| run: | | ||
| set -euxo pipefail |
Copilot
AI
Dec 6, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using set -euxo pipefail with a diagnostics step that should tolerate failures is problematic. The -e flag will cause the script to exit on the first command that returns a non-zero exit status, even though all commands have || true to prevent failures. While the || true will prevent individual command failures from stopping the script, the set -e is unnecessary here since this is a diagnostic step that should never fail.
Consider using set -uxo pipefail instead (without -e) for this diagnostic step, or remove set entirely since all commands already have || true fallbacks.
| set -euxo pipefail | |
| set -uxo pipefail |
| for i in 1 2 3; do | ||
| sudo apt-get install -y --no-install-recommends \ | ||
| -o Dpkg::Options::="--force-confdef" \ | ||
| -o Dpkg::Options::="--force-confold" \ | ||
| libssl-dev unixodbc-dev alien libaio1 gnupg2 curl \ | ||
| odbcinst1debian2 libodbc1 odbcinst || { | ||
| echo "apt-get install attempt $i failed; retrying in 10s..." | ||
| sleep 10 | ||
| continue | ||
| } | ||
| break | ||
| done |
Copilot
AI
Dec 6, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The retry logic has a subtle bug: if the last attempt (attempt 3) fails, the script will exit with a non-zero status due to set -e, but the loop will have already completed all iterations. This means the retry won't actually fail the step - it will silently succeed.
The issue is that after the loop completes all 3 iterations without success, there's no explicit check to verify if the installation actually succeeded. Consider adding a verification after the loop:
for i in 1 2 3; do
sudo apt-get install -y --no-install-recommends \
-o Dpkg::Options::="--force-confdef" \
-o Dpkg::Options::="--force-confold" \
libssl-dev unixodbc-dev alien libaio1 gnupg2 curl \
odbcinst1debian2 libodbc1 odbcinst && break || {
echo "apt-get install attempt $i failed; retrying in 10s..."
if [ "$i" -eq 3 ]; then
echo "All 3 attempts failed"
exit 1
fi
sleep 10
}
done| for i in 1 2 3; do | |
| sudo apt-get install -y --no-install-recommends \ | |
| -o Dpkg::Options::="--force-confdef" \ | |
| -o Dpkg::Options::="--force-confold" \ | |
| libssl-dev unixodbc-dev alien libaio1 gnupg2 curl \ | |
| odbcinst1debian2 libodbc1 odbcinst || { | |
| echo "apt-get install attempt $i failed; retrying in 10s..." | |
| sleep 10 | |
| continue | |
| } | |
| break | |
| done | |
| success=0 | |
| for i in 1 2 3; do | |
| sudo apt-get install -y --no-install-recommends \ | |
| -o Dpkg::Options::="--force-confdef" \ | |
| -o Dpkg::Options::="--force-confold" \ | |
| libssl-dev unixodbc-dev alien libaio1 gnupg2 curl \ | |
| odbcinst1debian2 libodbc1 odbcinst && { success=1; break; } || { | |
| echo "apt-get install attempt $i failed; retrying in 10s..." | |
| sleep 10 | |
| continue | |
| } | |
| done | |
| if [ "$success" -ne 1 ]; then | |
| echo "apt-get install failed after 3 attempts" | |
| exit 1 | |
| fi |
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: apt-dpkg-logs | ||
| path: ci-apt-logs |
Copilot
AI
Dec 6, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The artifact upload step uses a hardcoded path ci-apt-logs instead of $GITHUB_WORKSPACE/ci-apt-logs which is used in the diagnostic capture step. While this may work if the working directory is $GITHUB_WORKSPACE, it's inconsistent and could fail if the working directory changes.
For consistency and clarity, use the full path:
path: ${{ github.workspace }}/ci-apt-logsor ensure the path matches what's created in line 883.
| path: ci-apt-logs | |
| path: ${{ github.workspace }}/ci-apt-logs |
| run: | | ||
| set -euxo pipefail | ||
| curl -sSL -O https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb | ||
| sudo dpkg -i packages-microsoft-prod.deb |
Copilot
AI
Dec 6, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing DEBIAN_FRONTEND=noninteractive environment variable on the dpkg command. While the env is set at the step level, being explicit when calling dpkg can prevent potential interactive prompts if the environment isn't properly inherited.
Consider adding it explicitly to the dpkg command:
sudo DEBIAN_FRONTEND=noninteractive dpkg -i packages-microsoft-prod.debThis is especially important since this step had the -o Dpkg::Options:: flags for confdef/confold in the system dependencies step but those options are not applicable to dpkg command directly (they're apt-get options).
| sudo dpkg -i packages-microsoft-prod.deb | |
| sudo DEBIAN_FRONTEND=noninteractive dpkg -i packages-microsoft-prod.deb |
The
linux-gcc-cmake-odbcjob intermittently fails during apt/dpkg steps with no visible errors. Symptoms suggest interactive prompts, unmet dependencies, or transient network/disk issues.Changes
Made all apt/dpkg operations non-interactive:
DEBIAN_FRONTEND=noninteractiveon all package installation steps--force-confdefand--force-confoldto auto-resolve config conflictsAdded retry logic for transient failures:
Acquire::Retries=3for apt-get update operationsFixed dpkg dependency issues:
apt-get install -y -fafter dpkg installations to resolve unmet dependencies|| true) before fixing depsAdded failure diagnostics:
apt-dpkg-logs) for post-mortem analysisRe-run on failure
If failures persist, check the uploaded
apt-dpkg-logsartifact for apt/dpkg logs and system diagnostics.Original prompt
Problem
The GitHub Actions job linux-gcc-cmake-odbc on ubuntu-22.04 intermittently fails during apt/dpkg steps with no visible error in the logs. Symptoms indicate apt may be prompting interactively, dpkg -i may leave unmet dependencies, or runner disk/network/transient issues cause silent failures. We need to harden the workflow to make installs non-interactive, retry transient apt failures, fix dpkg unmet deps, capture apt/dpkg diagnostics on failure, and always upload those logs as artifacts so failures can be diagnosed.
Goal
Create a pull request that updates the workflow(s) under .github/workflows which define the job named linux-gcc-cmake-odbc. For each workflow file containing that job, replace the existing apt install / cleanup / dpkg steps with robust, non-interactive steps and add diagnostic upload steps. The change must target the main branch.
Required changes
Replace the existing steps that run:
with the following new sequence of steps (YAML snippet to be inserted in place of the original steps):
name: Pre-check runner disk & cleanup
run: |
echo "Disk usage before cleanup:"
df -h .
free -h
sudo rm -f /var/lib/dpkg/lock-frontend /var/cache/apt/archives/lock || true
sudo apt-get -y autoremove --purge || true
sudo apt-get -y clean || true
sudo rm -rf /usr/share/dotnet || true
sudo npm cache clean --force || true
sudo docker system prune -a --force || true
echo "Disk usage after cleanup:"
df -h .
name: Install basic system dependencies (robust)
env:
DEBIAN_FRONTEND: noninteractive
run: |
set -euxo pipefail
sudo rm -f /var/lib/dpkg/lock-frontend /var/cache/apt/archives/lock || true
sudo apt-get update -o Acquire::Retries=3
for i in 1 2 3; do
sudo apt-get install -y --no-install-recommends
-o Dpkg::Options::="--force-confdef"
-o Dpkg::Options::="--force-confold"
libssl-dev unixodbc-dev alien libaio1 gnupg2 curl
odbcinst1debian2 libodbc1 odbcinst || {
echo "apt-get install attempt $i failed; retrying in 10s..."
sleep 10
continue
}
break
done
name: Setup Oracle ODBC connector (.deb) and fix deps
env:
DEBIAN_FRONTEND: noninteractive
run: |
set -euxo pipefail
wget https://www.devart.com/odbc/oracle/devartodbcoracle_amd64.deb
sudo dpkg -i devartodbcoracle_amd64.deb || true
sudo apt-get update -o Acquire::Retries=3
sudo apt-get install -y -f
dpkg -l | grep -Ei 'devart|odbc|oracle' || true
name: Setup Microsoft packages & msodbcsql18
env:
DEBIAN_FRONTEND: noninteractive
run: |
set -euxo pipefail
curl -sSL -O https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb
sudo apt-get update -o Acquire::Retries=3
sudo ACCEPT_EULA=Y apt-get install -y msodbcsql18
name: Capture apt/dpkg/system diagnostics on failure
if: failure()
run: |
set -euxo pipefail
echo "===== APT / DPKG DIAGNOSTICS ====="
sudo tail -n +1 /var/log/apt/term.log || true
sudo tail -n +1 /var/log/apt/history.log || true
sudo tail -n +1 /var/log/dpkg.log || true
df -h || true
free -h || true
uname -a || true
dmesg --level=err,warn | tail -n 200 || true
mkdir -p $GITHUB_WORKSPACE/ci-apt-logs
sudo cp /var/log/apt/* $GITHUB_WORKSPACE/ci-apt-logs/ 2>/dev/null || true
sudo cp /var/log/dpkg.log $GITHUB_WORKSPACE/ci-apt-logs/ 2>/dev/null || true
ls -l $GITHUB_WORKSPACE/ci-apt-logs || true
name: Upload apt/dpkg logs
if: always()
uses: actions/upload-artifact@v4
with:
name: apt-dpkg-logs
path: ci-apt-logs
Preserve the remaining steps in the job (cmake, build, tests) unchanged.
Ensure the YAML indentation and syntax match existing workflow style.
Add a concise commit message and PR description explaining the changes and rationale (prevents interactive prompts, retries transient errors, captures logs).
Deliverable
Open a pull request on pocoproject/poco targeting the main branch with the changes described above. The PR should include:
This pull request was created as a result of the following prompt from Copilot chat.
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.