-
Notifications
You must be signed in to change notification settings - Fork 2
FOGL-10165 github workflow added to verify Package dependencies #115
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
Merged
Merged
Changes from 2 commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,342 @@ | ||
name: π§ͺ Verify Package Dependencies | ||
|
||
on: | ||
push: | ||
branches: ['*'] | ||
|
||
env: | ||
DEBIAN_FRONTEND: noninteractive | ||
|
||
jobs: | ||
verify-dependencies: | ||
name: π οΈ ${{ matrix.os }}-${{ matrix.arch }} | ||
runs-on: ${{ matrix.runs_on }} | ||
timeout-minutes: 30 | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
include: | ||
- os: ubuntu-22.04 | ||
arch: x86_64 | ||
runs_on: ubuntu-22.04 | ||
codename: jammy | ||
- os: ubuntu-22.04 | ||
arch: aarch64 | ||
runs_on: ubuntu-22.04 | ||
codename: jammy | ||
- os: ubuntu-24.04 | ||
arch: x86_64 | ||
runs_on: ubuntu-24.04 | ||
codename: noble | ||
- os: ubuntu-24.04 | ||
arch: aarch64 | ||
runs_on: ubuntu-24.04 | ||
codename: noble | ||
|
||
steps: | ||
- name: Checkout repository | ||
uses: actions/checkout@v4 | ||
with: | ||
fetch-depth: 1 | ||
|
||
- name: Set up environment | ||
run: | | ||
echo "CONTROL_FILE=packages/Debian/${{ matrix.arch }}/DEBIAN/control" >> $GITHUB_ENV | ||
echo "REPORT=dep_report_${{ matrix.os }}_${{ matrix.arch }}.md" >> $GITHUB_ENV | ||
|
||
- name: Validate control file exists | ||
run: | | ||
if [ ! -f "$CONTROL_FILE" ]; then | ||
echo "β Control file missing: $CONTROL_FILE" | ||
echo "Available files in packages/Debian/:" | ||
find packages/Debian/ -name "control" 2>/dev/null || echo "No control files found" | ||
exit 1 | ||
fi | ||
echo "β Control file found: $CONTROL_FILE" | ||
|
||
- name: Verify dependencies & generate report | ||
run: | | ||
set -euo pipefail | ||
|
||
# Initialize report | ||
cat > "$REPORT" << EOF | ||
## π¦ Dependency Verification Report | ||
|
||
**Platform:** ${{ matrix.arch }} on ${{ matrix.os }} (${{ matrix.codename }}) | ||
**Generated:** $(date -u '+%Y-%m-%d %H:%M:%S UTC') | ||
**Workflow:** ${GITHUB_WORKFLOW} - Run #${GITHUB_RUN_NUMBER} | ||
|
||
EOF | ||
|
||
# Enhanced dependency extraction function | ||
extract_deps() { | ||
local field="$1" | ||
awk -v field="$field" ' | ||
BEGIN { found=0; deps="" } | ||
{ | ||
if ($0 ~ "^" field ":") { | ||
found=1 | ||
gsub("^" field ":[[:space:]]*", "") | ||
deps = $0 | ||
} else if (found && $0 ~ "^[[:space:]]") { | ||
# Continuation line (starts with whitespace) | ||
gsub("^[[:space:]]*", "") | ||
if ($0 != "") { | ||
deps = deps " " $0 | ||
} | ||
} else if (found && $0 !~ "^[[:space:]]" && $0 != "") { | ||
# New field found, stop processing | ||
print deps | ||
exit | ||
} | ||
} | ||
END { if (found && deps != "") print deps } | ||
' "$CONTROL_FILE" | \ | ||
tr ',' '\n' | \ | ||
sed -E 's/\([^)]*\)//g' | \ | ||
sed -E 's/\[[^]]*\]//g' | \ | ||
awk '{gsub(/^[[:space:]]+|[[:space:]]+$/, ""); if ($1 != "") print $1}' | \ | ||
sort -u | ||
} | ||
|
||
# Function to detect and resolve version placeholders | ||
resolve_version_placeholders() { | ||
local control_file="$1" | ||
local temp_file="" | ||
|
||
echo "π Checking for version placeholders in $(basename "$control_file")..." >&2 | ||
|
||
# Check for BOOST_VER placeholder | ||
if grep -q "{{BOOST_VER}}" "$control_file"; then | ||
echo "π¦ Found {{BOOST_VER}} placeholder, resolving Boost version..." >&2 | ||
|
||
local boost_version="" | ||
local boost_suffix="" | ||
|
||
# Method 1: Check installed libboost-dev package | ||
if [ -z "$boost_version" ]; then | ||
boost_version=$(dpkg -l 2>/dev/null | grep "libboost-dev" | awk '{print $3}' | grep -oP '^\d+\.\d+\.\d+' | head -1 || true) | ||
[ -n "$boost_version" ] && echo "β Found installed Boost version: $boost_version" >&2 | ||
fi | ||
|
||
# Method 2: Check available package version | ||
if [ -z "$boost_version" ]; then | ||
boost_version=$(apt-cache policy libboost-dev 2>/dev/null | grep "Candidate:" | awk '{print $2}' | grep -oP '^\d+\.\d+\.\d+' | head -1 || true) | ||
[ -n "$boost_version" ] && echo "β Found available Boost version: $boost_version" >&2 | ||
fi | ||
|
||
# Determine the correct Boost package suffix format | ||
echo "π Determining correct Boost package naming format..." >&2 | ||
|
||
local boost_major_minor=$(echo "$boost_version" | cut -d'.' -f1-2) | ||
local boost_major_minor_no_dot=$(echo "$boost_major_minor" | tr -d '.') | ||
|
||
# Test different naming conventions | ||
if apt-cache show "libboost-system${boost_version}" >/dev/null 2>&1; then | ||
boost_suffix="$boost_version" | ||
echo "β Found format: libboost-system${boost_suffix}" >&2 | ||
elif apt-cache show "libboost-system${boost_major_minor}" >/dev/null 2>&1; then | ||
boost_suffix="$boost_major_minor" | ||
echo "β Found format: libboost-system${boost_suffix}" >&2 | ||
elif apt-cache show "libboost-system${boost_major_minor_no_dot}" >/dev/null 2>&1; then | ||
boost_suffix="$boost_major_minor_no_dot" | ||
echo "β Found format: libboost-system${boost_suffix}" >&2 | ||
else | ||
# Fallback to the most common format | ||
boost_suffix="$boost_major_minor" | ||
echo "β οΈ Could not detect format, using default: libboost-system${boost_suffix}" >&2 | ||
fi | ||
|
||
echo "π’ Final Boost package suffix: $boost_suffix" >&2 | ||
|
||
# Create temporary file if not already created | ||
if [ -z "$temp_file" ]; then | ||
temp_file=$(mktemp) | ||
cp "$control_file" "$temp_file" | ||
fi | ||
|
||
# Replace BOOST_VER placeholder | ||
sed -i "s/{{BOOST_VER}}/${boost_suffix}/g" "$temp_file" | ||
echo "β Resolved {{BOOST_VER}} to ${boost_suffix}" >&2 | ||
|
||
# Show resolved dependencies for verification | ||
echo "π Resolved Boost dependencies:" >&2 | ||
grep -E "libboost.*${boost_suffix}" "$temp_file" >&2 || true | ||
fi | ||
|
||
# TODO: Add more placeholder handlers here in the future | ||
# Example for future use: | ||
# if grep -q "{{PYTHON_VER}}" "$control_file"; then | ||
# echo "π¦ Found {{PYTHON_VER}} placeholder, resolving Python version..." | ||
# # Add Python version detection logic here | ||
# fi | ||
|
||
# Return the path to the resolved file (or original if no changes) | ||
if [ -n "$temp_file" ]; then | ||
echo "π Using temporary control file with resolved placeholders: $temp_file" >&2 | ||
echo "$temp_file" | ||
else | ||
echo "βΉοΈ No version placeholders found, using original file" >&2 | ||
echo "$control_file" | ||
fi | ||
} | ||
|
||
# Resolve version placeholders in control file | ||
RESOLVED_CONTROL_FILE=$(resolve_version_placeholders "$CONTROL_FILE") | ||
|
||
# Store the temporary file path for cleanup later | ||
if [ "$RESOLVED_CONTROL_FILE" != "$CONTROL_FILE" ]; then | ||
TEMP_CONTROL_FILE="$RESOLVED_CONTROL_FILE" | ||
echo "π Using resolved control file: $TEMP_CONTROL_FILE" | ||
else | ||
echo "π Using original control file: $CONTROL_FILE" | ||
fi | ||
|
||
# Update CONTROL_FILE to point to the resolved file | ||
CONTROL_FILE="$RESOLVED_CONTROL_FILE" | ||
|
||
# Extract dependencies | ||
echo "π Extracting dependencies from control file..." | ||
echo "π Using control file: $CONTROL_FILE" | ||
|
||
BUILD_DEPS=$(extract_deps "Build-Depends") | ||
RUNTIME_DEPS=$(extract_deps "Depends") | ||
RECOMMENDS=$(extract_deps "Recommends") | ||
SUGGESTS=$(extract_deps "Suggests") | ||
|
||
# Validate extraction results | ||
BUILD_COUNT=$(echo "$BUILD_DEPS" | wc -w) | ||
RUNTIME_COUNT=$(echo "$RUNTIME_DEPS" | wc -w) | ||
|
||
echo "π Extraction results:" | ||
echo " - Build dependencies: $BUILD_COUNT packages" | ||
echo " - Runtime dependencies: $RUNTIME_COUNT packages" | ||
echo " - Recommended packages: $(echo "$RECOMMENDS" | wc -w) packages" | ||
echo " - Suggested packages: $(echo "$SUGGESTS" | wc -w) packages" | ||
|
||
if [ $BUILD_COUNT -eq 0 ] && [ $RUNTIME_COUNT -eq 0 ]; then | ||
echo "β No dependencies extracted! This might indicate a parsing error." | ||
echo "Control file content:" | ||
head -20 "$CONTROL_FILE" | ||
exit 1 | ||
fi | ||
|
||
# Update package cache with retry | ||
echo "π₯ Updating package cache..." | ||
for i in {1..3}; do | ||
if sudo apt-get update -qq; then | ||
break | ||
elif [ $i -eq 3 ]; then | ||
echo "β Failed to update package cache after 3 attempts" | ||
exit 1 | ||
else | ||
echo "β οΈ Package cache update failed, retrying in 10s..." | ||
sleep 10 | ||
fi | ||
done | ||
|
||
# Enhanced dependency checking function | ||
check_dependencies() { | ||
local label="$1" | ||
local pkgs="$2" | ||
local is_critical="$3" | ||
local fail=0 | ||
local total=0 | ||
local available=0 | ||
|
||
echo "" >> "$REPORT" | ||
echo "## $label" >> "$REPORT" | ||
|
||
if [ -z "$pkgs" ]; then | ||
echo "- βΉοΈ No $label specified" >> "$REPORT" | ||
return 0 | ||
fi | ||
|
||
for pkg in $pkgs; do | ||
total=$((total + 1)) | ||
|
||
# Skip empty package names | ||
[ -z "$pkg" ] && continue | ||
|
||
# Check if package is available | ||
if apt-cache show "$pkg" > /dev/null 2>&1; then | ||
# Get package version info | ||
version=$(apt-cache policy "$pkg" 2>/dev/null | grep "Candidate:" | awk '{print $2}' || echo "unknown") | ||
echo "- β **$pkg** (version: $version)" >> "$REPORT" | ||
available=$((available + 1)) | ||
else | ||
echo "- β **$pkg** - Package not found in repositories" >> "$REPORT" | ||
|
||
# Try to find similar packages | ||
similar=$(apt-cache search "^$pkg" 2>/dev/null | head -3 | cut -d' ' -f1 | tr '\n' ', ' | sed 's/,$//') | ||
if [ -n "$similar" ]; then | ||
echo " - π‘ Similar packages: $similar" >> "$REPORT" | ||
fi | ||
|
||
if [ "$is_critical" = "true" ]; then | ||
fail=1 | ||
fi | ||
fi | ||
done | ||
|
||
# Add summary | ||
echo "" >> "$REPORT" | ||
echo "**Summary:** $available/$total packages available" >> "$REPORT" | ||
|
||
if [ $fail -eq 1 ]; then | ||
echo "β οΈ **Critical dependencies missing!**" >> "$REPORT" | ||
fi | ||
|
||
return $fail | ||
} | ||
|
||
# Check all dependency types | ||
check_dependencies "π¨ Build Dependencies" "$BUILD_DEPS" "true" || exit 1 | ||
check_dependencies "π Runtime Dependencies" "$RUNTIME_DEPS" "true" || exit 1 | ||
check_dependencies "π‘ Recommended Packages" "$RECOMMENDS" "false" || true | ||
check_dependencies "π§ Suggested Packages" "$SUGGESTS" "false" || true | ||
|
||
# Add final summary | ||
cat >> "$REPORT" << EOF | ||
|
||
--- | ||
|
||
## β Verification Complete | ||
|
||
All dependencies are accessible for ${{ matrix.arch }} on ${{ matrix.os }} (${{ matrix.codename }}). | ||
|
||
EOF | ||
|
||
# Cleanup temporary file if created | ||
if [ -n "${TEMP_CONTROL_FILE:-}" ] && [ -f "$TEMP_CONTROL_FILE" ]; then | ||
rm -f "$TEMP_CONTROL_FILE" | ||
echo "π§Ή Cleaned up temporary control file" | ||
fi | ||
|
||
- name: Validate report was generated | ||
run: | | ||
if [ ! -f "$REPORT" ] || [ ! -s "$REPORT" ]; then | ||
echo "β Report file is missing or empty" | ||
exit 1 | ||
fi | ||
echo "β Report generated successfully ($(wc -l < "$REPORT") lines)" | ||
|
||
- name: Add summary to job | ||
if: always() | ||
run: | | ||
echo "# π¦ Summary" >> $GITHUB_STEP_SUMMARY | ||
echo "" >> $GITHUB_STEP_SUMMARY | ||
if [ -f "$REPORT" ]; then | ||
cat "$REPORT" >> $GITHUB_STEP_SUMMARY | ||
else | ||
echo "β Report generation failed" >> $GITHUB_STEP_SUMMARY | ||
fi | ||
|
||
- name: Check for failures | ||
if: failure() | ||
run: | | ||
echo "β Dependency verification failed for ${{ matrix.os }} (${{ matrix.arch }})" | ||
echo "This indicates build or runtime dependencies are missing." | ||
echo "Please review the generated report and update the control file or repository configuration." | ||
exit 1 | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.