Skip to content

Build App Packages and Collect App Information #145

Build App Packages and Collect App Information

Build App Packages and Collect App Information #145

name: Build App Packages and Collect App Information
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * *" # Run at midnight UTC every day
jobs:
build:
runs-on: macos-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.PAT }}
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: "3.x"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install requests
- name: Make scrapers executable
run: chmod +x .github/scripts/scrapers/*.sh
- name: Collect app information
run: python .github/scripts/collect_app_info.py
- name: Find apps needing packaging
id: find-apps
run: |
echo "Finding apps that need special packaging..."
apps_to_build=()
for file in Apps/*.json; do
if [ -f "$file" ]; then
type=$(jq -r '.type // empty' "$file")
if [ "$type" = "app" ] || [ "$type" = "pkg_in_dmg" ]; then
app_name=$(basename "$file" .json)
url=$(jq -r '.url' "$file")
apps_to_build+=("$app_name:$url")
fi
fi
done
echo "APPS_TO_BUILD=${apps_to_build[*]}" >> $GITHUB_ENV
echo "Found apps: ${apps_to_build[*]}"
- name: Create supported_apps.json
run: |
python - <<EOF
import json
import os
import re
apps_folder = "Apps"
supported_apps = {}
for filename in os.listdir(apps_folder):
if filename.endswith(".json"):
app_name = os.path.splitext(filename)[0]
supported_apps[app_name] = f"https://raw.githubusercontent.com/ugurkocde/IntuneBrew/main/Apps/{filename}"
# Sort the dictionary alphabetically by keys
supported_apps = dict(sorted(supported_apps.items()))
with open("supported_apps.json", "w") as f:
json.dump(supported_apps, f, indent=4)
# Update README with total number of apps
total_apps = len(supported_apps)
with open("README.md", "r") as f:
readme_content = f.read()
# Create a badge-style apps count
apps_count_pattern = r'<p>\s*<a href="#-supported-applications">\s*<img src="https://img\.shields\.io/badge/Apps_Available-\d+-2ea44f\?style=flat"[^>]*>\s*</a>\s*</p>'
new_apps_badge = f' <p>\n <a href="#-supported-applications">\n <img src="https://img.shields.io/badge/Apps_Available-{total_apps}-2ea44f?style=flat" alt="TotalApps"/>\n </a>\n </p>'
# Replace the existing badge with the new one, or add if not found
if re.search(apps_count_pattern, readme_content):
readme_content = re.sub(apps_count_pattern, new_apps_badge, readme_content)
else:
# If no badge exists, add after the first paragraph in the centered div
readme_content = re.sub(r'( </p>)\n</div>', f'\\1\n{new_apps_badge}\n</div>', readme_content)
with open("README.md", "w") as f:
f.write(readme_content)
print(f"Updated README.md with {total_apps} apps badge")
EOF
- name: Process apps
if: env.APPS_TO_BUILD != ''
env:
AZURE_STORAGE_CONNECTION_STRING: ${{ secrets.AZURE_STORAGE_CONNECTION_STRING }}
run: |
WORKSPACE_DIR=$(pwd)
for app_info in $APPS_TO_BUILD; do
IFS=':' read -r app_name url <<< "$app_info"
echo "🔄 Processing $app_name..."
# Check if JSON file exists
if [ ! -f "$WORKSPACE_DIR/Apps/${app_name}.json" ]; then
echo "📝 JSON file for $app_name doesn't exist. Creating new JSON file..."
cat > "$WORKSPACE_DIR/Apps/${app_name}.json" << 'EOF'
{
"display_name": "APP_NAME",
"version": "0.0.0",
"url": "URL",
"type": "app",
"installer_type": "pkg",
"download_page": "",
"previous_version": ""
}
EOF
sed -i '' "s/APP_NAME/$app_name/g" "$WORKSPACE_DIR/Apps/${app_name}.json"
sed -i '' "s|URL|$url|g" "$WORKSPACE_DIR/Apps/${app_name}.json"
echo "✅ Created new JSON file for $app_name"
else
echo "📄 Using existing JSON file for $app_name"
fi
# Get version and type from JSON file
version=$(jq -r '.version' "$WORKSPACE_DIR/Apps/${app_name}.json")
app_type=$(jq -r '.type' "$WORKSPACE_DIR/Apps/${app_name}.json")
echo "📦 Version: $version"
echo "🏷️ Type: $app_type"
# Skip if not a supported type
if [ "$app_type" != "app" ] && [ "$app_type" != "pkg_in_dmg" ] && [ "$app_type" != "pkg_in_pkg" ]; then
echo "⏭️ Skipping URL update for $app_name as it's not of type 'app', 'pkg_in_dmg', or 'pkg_in_pkg'"
continue
fi
# List existing versions of this app in Azure storage
existing_versions=$(az storage blob list --container-name pkg --prefix "${app_name}_" --query "[].name" -o tsv)
# Check if the exact version already exists
if echo "$existing_versions" | grep -q "^${app_name}_${version}.pkg$"; then
echo "Package ${app_name}_${version}.pkg already exists in Azure storage. Skipping..."
# Update the JSON file with Azure URL
azure_url="https://intunebrew.blob.core.windows.net/pkg/${app_name}_${version}.pkg"
# Get current version to store as previous_version
current_version=$(jq -r '.version' "$WORKSPACE_DIR/Apps/${app_name}.json")
jq --arg url "$azure_url" --arg version "$version" --arg prev_version "$current_version" '.url = $url | .version = $version | .previous_version = $prev_version' "$WORKSPACE_DIR/Apps/${app_name}.json" > temp.json && mv temp.json "$WORKSPACE_DIR/Apps/${app_name}.json"
continue
fi
if [ "$app_type" = "pkg_in_pkg" ]; then
echo "🔍 Processing PKG in PKG for $app_name..."
echo "📥 Downloading PKG from: $url"
# Set download path
download_path="$HOME/Desktop/${app_name}"
# Download PKG
curl -L -o "${download_path}.pkg" "$url"
if [ $? -eq 0 ]; then
echo "✅ PKG download successful"
ls -lh "${download_path}.pkg"
# Create temporary directory for extraction
echo "📂 Creating temporary directory for extraction"
temp_dir="${download_path}_extracted"
mkdir -p "$temp_dir"
# Extract PKG
echo "🔓 Extracting outer PKG..."
pkgutil --expand "${download_path}.pkg" "$temp_dir"
if [ $? -eq 0 ]; then
echo "✅ PKG extraction successful"
echo "📁 Extracted contents:"
ls -R "$temp_dir"
# Find inner PKG file
echo "🔍 Searching for inner PKG file..."
inner_pkg=$(find "$temp_dir" -name "*.pkg" -print -quit)
if [ -n "$inner_pkg" ]; then
echo "✅ Found inner PKG file: $inner_pkg"
echo "📦 Package size: $(ls -lh "$inner_pkg" | awk '{print $5}')"
# Copy inner PKG file with version in filename
echo "📋 Copying inner PKG file to ${app_name}_${version}.pkg"
cp "$inner_pkg" "${app_name}_${version}.pkg"
# Calculate SHA256 hash
echo "🔐 Calculating SHA256 hash..."
file_hash=$(shasum -a 256 "${app_name}_${version}.pkg" | awk '{print $1}')
echo "📝 SHA256: $file_hash"
# Upload to Azure
echo "☁️ Uploading to Azure Blob Storage..."
az storage blob upload \
--container-name pkg \
--file "${app_name}_${version}.pkg" \
--name "${app_name}_${version}.pkg" \
--overwrite true
if [ $? -eq 0 ]; then
echo "✅ Upload successful"
# Update JSON with Azure URL and SHA256
echo "📝 Updating JSON file with new Azure URL and SHA256..."
azure_url="https://intunebrew.blob.core.windows.net/pkg/${app_name}_${version}.pkg"
jq --arg url "$azure_url" --arg filename "${app_name}_${version}.pkg" --arg sha "$file_hash" '.url = $url | .fileName = $filename | .sha = $sha' "$WORKSPACE_DIR/Apps/${app_name}.json" > temp.json && mv temp.json "$WORKSPACE_DIR/Apps/${app_name}.json"
if [ $? -eq 0 ]; then
echo "✅ JSON file updated successfully"
echo "🔗 New URL: $azure_url"
else
echo "❌ Failed to update JSON file"
fi
else
echo "❌ Failed to upload to Azure"
fi
else
echo "❌ No inner PKG file found in extracted contents"
echo "📁 Extracted contents:"
ls -R "$temp_dir"
fi
else
echo "❌ Failed to extract PKG"
fi
# Cleanup
echo "🧹 Cleaning up..."
echo "🗑️ Removing temporary files..."
rm -f "${download_path}.pkg"
rm -rf "$temp_dir"
echo "✨ Cleanup complete"
else
echo "❌ Failed to download PKG"
fi
elif [ "$app_type" = "pkg_in_dmg" ]; then
echo "🔍 Processing PKG in DMG for $app_name..."
echo "📥 Downloading DMG from: $url"
# Set download path
download_path="$HOME/Desktop/${app_name}"
# Download DMG
curl -L -o "${download_path}.dmg" "$url"
if [ $? -eq 0 ]; then
echo "✅ DMG download successful"
ls -lh "${download_path}.dmg"
else
echo "❌ Failed to download DMG"
continue
fi
# Create mount point
echo "📂 Creating mount point at ${download_path}_mount"
mkdir -p "${download_path}_mount"
# Mount DMG
echo "💿 Mounting DMG..."
hdiutil attach "${download_path}.dmg" -mountpoint "${download_path}_mount" -nobrowse
if [ $? -eq 0 ]; then
echo "✅ DMG mounted successfully"
echo "📁 Mount point contents:"
ls -la "${download_path}_mount"
else
echo "❌ Failed to mount DMG"
rm -f "${download_path}.dmg"
rm -rf "${download_path}_mount"
continue
fi
# Find PKG file
echo "🔍 Searching for PKG file..."
pkg_file=$(find "${download_path}_mount" -name "*.pkg" -print -quit)
if [ -n "$pkg_file" ]; then
echo "✅ Found PKG file: $pkg_file"
echo "📦 Package size: $(ls -lh "$pkg_file" | awk '{print $5}')"
# Copy PKG file with version in filename
echo "📋 Copying PKG file to ${app_name}_${version}.pkg"
cp "$pkg_file" "${app_name}_${version}.pkg"
# Calculate SHA256 hash
echo "🔐 Calculating SHA256 hash..."
file_hash=$(shasum -a 256 "${app_name}_${version}.pkg" | awk '{print $1}')
echo "📝 SHA256: $file_hash"
# Upload to Azure
echo "☁️ Uploading to Azure Blob Storage..."
az storage blob upload \
--container-name pkg \
--file "${app_name}_${version}.pkg" \
--name "${app_name}_${version}.pkg" \
--overwrite true
if [ $? -eq 0 ]; then
echo "✅ Upload successful"
# Update JSON with Azure URL and SHA256
echo "📝 Updating JSON file with new Azure URL and SHA256..."
azure_url="https://intunebrew.blob.core.windows.net/pkg/${app_name}_${version}.pkg"
jq --arg url "$azure_url" --arg filename "${app_name}_${version}.pkg" --arg sha "$file_hash" '.url = $url | .fileName = $filename | .sha = $sha' "$WORKSPACE_DIR/Apps/${app_name}.json" > temp.json && mv temp.json "$WORKSPACE_DIR/Apps/${app_name}.json"
if [ $? -eq 0 ]; then
echo "✅ JSON file updated successfully"
echo "🔗 New URL: $azure_url"
else
echo "❌ Failed to update JSON file"
fi
else
echo "❌ Failed to upload to Azure"
fi
else
echo "❌ No PKG file found in DMG for $app_name"
echo "📁 Contents of mount point:"
ls -R "${download_path}_mount"
fi
# Cleanup
echo "🧹 Cleaning up..."
echo "💿 Unmounting DMG..."
hdiutil detach "${download_path}_mount"
echo "🗑️ Removing temporary files..."
rm -f "${download_path}.dmg"
rm -rf "${download_path}_mount"
echo "✨ Cleanup complete"
else
# Download app
echo "Downloading $app_name..."
download_path="$HOME/Desktop/${app_name}"
if [[ "$url" == *".zip" ]]; then
curl -L -o "${download_path}.zip" "$url"
cd "$HOME/Desktop"
# Extract zip while excluding __MACOSX directory
unzip -q -d "${app_name}_extracted" "${download_path}.zip"
rm "${download_path}.zip"
elif [[ "$url" == *".tar.xz" ]]; then
echo "📦 Processing tar.xz archive for $app_name..."
curl -L -o "${download_path}.tar.xz" "$url"
cd "$HOME/Desktop"
# Extract tar.xz
echo "📂 Creating extraction directory..."
mkdir -p "${app_name}_extracted"
echo "🔓 Extracting tar.xz archive..."
tar -xf "${download_path}.tar.xz" -C "${app_name}_extracted"
echo "🗑️ Cleaning up downloaded archive..."
rm "${download_path}.tar.xz"
echo "📁 Extracted contents:"
ls -R "${app_name}_extracted"
elif [[ "$url" == *".tar.bz2" ]]; then
echo "📦 Processing tar.bz2 archive for $app_name..."
curl -L -o "${download_path}.tar.bz2" "$url"
cd "$HOME/Desktop"
# Extract tar.bz2
echo "📂 Creating extraction directory..."
mkdir -p "${app_name}_extracted"
echo "🔓 Extracting tar.bz2 archive..."
tar -xjf "${download_path}.tar.bz2" -C "${app_name}_extracted"
echo "🗑️ Cleaning up downloaded archive..."
rm "${download_path}.tar.bz2"
echo "📁 Extracted contents:"
ls -R "${app_name}_extracted"
elif [[ "$url" == *".tar.gz" ]]; then
echo "📦 Processing tar.gz archive for $app_name..."
curl -L -o "${download_path}.tar.gz" "$url"
cd "$HOME/Desktop"
# Extract tar.gz
echo "📂 Creating extraction directory..."
mkdir -p "${app_name}_extracted"
echo "🔓 Extracting tar.gz archive..."
tar -xzf "${download_path}.tar.gz" -C "${app_name}_extracted"
echo "🗑️ Cleaning up downloaded archive..."
rm "${download_path}.tar.gz"
echo "📁 Extracted contents:"
ls -R "${app_name}_extracted"
else
curl -L -o "${download_path}.zip" "$url"
cd "$HOME/Desktop"
# Default to zip extraction
unzip -q -d "${app_name}_extracted" "${download_path}.zip"
rm "${download_path}.zip"
fi
# First try to find .app file recursively, excluding __MACOSX directory
echo "🔍 Searching for .app file recursively..."
app_file=$(find "${app_name}_extracted" -type d -name "*.app" ! -path "*/__MACOSX/*" -print -quit)
if [ -z "$app_file" ]; then
echo "❌ No .app file found, searching for .pkg file..."
pkg_file=$(find "${app_name}_extracted" -type f -name "*.pkg" ! -path "*/__MACOSX/*" -print -quit)
if [ -n "$pkg_file" ]; then
echo "✅ Found .pkg file: $pkg_file"
echo "📦 Package size: $(ls -lh "$pkg_file" | awk '{print $5}')"
# Copy PKG file with version in filename
echo "📋 Copying PKG file to ${app_name}_${version}.pkg"
cp "$pkg_file" "${app_name}_${version}.pkg"
# Calculate SHA256 hash
echo "🔐 Calculating SHA256 hash..."
file_hash=$(shasum -a 256 "${app_name}_${version}.pkg" | awk '{print $1}')
echo "📝 SHA256: $file_hash"
# Upload to Azure
echo "☁️ Uploading to Azure Blob Storage..."
az storage blob upload \
--container-name pkg \
--file "${app_name}_${version}.pkg" \
--name "${app_name}_${version}.pkg" \
--overwrite true
if [ $? -eq 0 ]; then
echo "✅ Upload successful"
# Update JSON with Azure URL and SHA256
echo "📝 Updating JSON file with new Azure URL and SHA256..."
azure_url="https://intunebrew.blob.core.windows.net/pkg/${app_name}_${version}.pkg"
jq --arg url "$azure_url" --arg filename "${app_name}_${version}.pkg" --arg sha "$file_hash" '.url = $url | .fileName = $filename | .sha = $sha' "$WORKSPACE_DIR/Apps/${app_name}.json" > temp.json && mv temp.json "$WORKSPACE_DIR/Apps/${app_name}.json"
if [ $? -eq 0 ]; then
echo "✅ JSON file updated successfully"
echo "🔗 New URL: $azure_url"
else
echo "❌ Failed to update JSON file"
fi
else
echo "❌ Failed to upload to Azure"
fi
# Clean up and continue to next app
cd "$WORKSPACE_DIR"
rm -rf "${app_name}_extracted"
continue
else
echo "❌ No .app or .pkg file found for $app_name"
echo " Extracted contents:"
ls -R "${app_name}_extracted"
cd "$WORKSPACE_DIR"
rm -rf "${app_name}_extracted"
continue
fi
fi
echo "✅ Found .app file: $app_file"
# Build PKG with version in filename
echo "Building PKG for $app_name version $version..."
pkgbuild --install-location /Applications --component "$app_file" "${app_name}_${version}.pkg"
# Calculate SHA256 hash
echo "🔐 Calculating SHA256 hash..."
file_hash=$(shasum -a 256 "${app_name}_${version}.pkg" | awk '{print $1}')
echo "📝 SHA256: $file_hash"
# Upload to Azure with version in filename
echo "Uploading $app_name version $version to Azure Blob Storage..."
az storage blob upload \
--container-name pkg \
--file "${app_name}_${version}.pkg" \
--name "${app_name}_${version}.pkg" \
--overwrite true
# Delete older versions of this app from Azure storage
if [ ! -z "$existing_versions" ]; then
echo "Cleaning up older versions of $app_name..."
echo "$existing_versions" | while read -r blob_name; do
if [ ! -z "$blob_name" ] && [ "$blob_name" != "${app_name}_${version}.pkg" ]; then
echo "Deleting old version: $blob_name"
az storage blob delete --container-name pkg --name "$blob_name"
fi
done
fi
# Update the JSON file with Azure URL, filename and SHA256
azure_url="https://intunebrew.blob.core.windows.net/pkg/${app_name}_${version}.pkg"
jq --arg url "$azure_url" --arg filename "${app_name}_${version}.pkg" --arg sha "$file_hash" '.url = $url | .fileName = $filename | .sha = $sha' "$WORKSPACE_DIR/Apps/${app_name}.json" > temp.json && mv temp.json "$WORKSPACE_DIR/Apps/${app_name}.json"
# Cleanup
sudo rm -rf "${app_name}_extracted"
fi
echo "✅ Completed processing $app_name"
echo "------------------------------------------------"
done
- name: Commit and push changes
run: |
git config --local user.email "[email protected]"
git config --local user.name "GitHub Action"
git add Apps/*.json supported_apps.json README.md
git commit -m "Update app information and supported apps list" || exit 0
git push https://${{ secrets.PAT }}@github.com/${{ github.repository }}.git