Add workflows for validation on new FMAs only (#35888)

Currently none of our FMA validation runs are completing successfully.
With 100+ FMAs now available in our library. the workflow for validating
new apps is taking over an hour to run and prone to timeouts because it
validates all apps on every pull request, including checking Windows
apps when a new macOS app is submitted. These new workflows validate
only newly added FMAs while keeping the workflows for validating all
apps available for manual runs.

---------

Co-authored-by: Luke Heath <luke@fleetdm.com>
This commit is contained in:
Allen Houchins
2025-11-24 15:00:27 -06:00
committed by GitHub
co-authored by Luke Heath
parent d8b4cd90a5
commit 2bc8fb064d
6 changed files with 467 additions and 12 deletions
+104
View File
@@ -0,0 +1,104 @@
#!/bin/bash
# Script to detect changed/new maintained apps in a PR
# This script compares the PR branch with the base branch to find:
# 1. New apps added to apps.json
# 2. Apps with changed manifest files
set -euo pipefail
# Get repository root
REPO_ROOT="${GITHUB_WORKSPACE:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
APPS_JSON="${REPO_ROOT}/ee/maintained-apps/outputs/apps.json"
OUTPUTS_DIR="${REPO_ROOT}/ee/maintained-apps/outputs"
# Base branch (usually main or the PR's base branch)
# In GitHub Actions, GITHUB_BASE_REF is set for pull_request events
BASE_BRANCH="${GITHUB_BASE_REF:-main}"
# Use origin/ prefix for remote branch reference
BASE_BRANCH_REF="origin/${BASE_BRANCH}"
# Check if jq is available
if ! command -v jq &> /dev/null; then
echo "Error: jq is required but not installed" >&2
exit 1
fi
# Function to extract app slugs from apps.json
extract_slugs() {
local apps_file="$1"
if [ ! -f "$apps_file" ]; then
echo ""
return
fi
jq -r '.apps[].slug' "$apps_file" | sort
}
# Function to extract app slugs from changed manifest files
extract_slugs_from_changed_manifests() {
local changed_files="$1"
local slugs=()
while IFS= read -r file; do
# Extract slug from path like: outputs/app-name/darwin.json or outputs/app-name/windows.json
if [[ "$file" =~ outputs/([^/]+)/(darwin|windows)\.json$ ]]; then
app_name="${BASH_REMATCH[1]}"
platform="${BASH_REMATCH[2]}"
slug="${app_name}/${platform}"
slugs+=("$slug")
fi
done <<< "$changed_files"
# Remove duplicates and sort
printf '%s\n' "${slugs[@]}" | sort -u
}
# Get changed files in outputs directory
echo "Detecting changed files in outputs directory..."
echo "Comparing HEAD with ${BASE_BRANCH_REF}..."
# Use merge-base to find the common ancestor for comparison
MERGE_BASE=$(git merge-base "${BASE_BRANCH_REF}" HEAD 2>/dev/null || echo "${BASE_BRANCH_REF}")
CHANGED_FILES=$(git diff --name-only "$MERGE_BASE" HEAD -- "ee/maintained-apps/outputs/" 2>/dev/null || echo "")
# Extract slugs from changed manifest files
CHANGED_MANIFEST_SLUGS=$(extract_slugs_from_changed_manifests "$CHANGED_FILES")
# Get current apps.json slugs
CURRENT_SLUGS=$(extract_slugs "$APPS_JSON")
# Get base branch apps.json slugs
echo "Fetching base branch apps.json from ${MERGE_BASE}..."
BASE_APPS_JSON=$(git show "${MERGE_BASE}:ee/maintained-apps/outputs/apps.json" 2>/dev/null || echo "")
BASE_SLUGS=""
if [ -n "$BASE_APPS_JSON" ]; then
BASE_SLUGS=$(echo "$BASE_APPS_JSON" | jq -r '.apps[].slug' | sort)
else
echo "Warning: Could not find apps.json in base branch, treating all current apps as new"
fi
# Find new slugs in apps.json
NEW_SLUGS=$(comm -13 <(echo "$BASE_SLUGS" || echo "") <(echo "$CURRENT_SLUGS" || echo "") || echo "")
# Combine all changed slugs (from manifest changes and new apps)
ALL_CHANGED_SLUGS=$(printf '%s\n' "$CHANGED_MANIFEST_SLUGS" "$NEW_SLUGS" | grep -v '^$' | sort -u)
# Output results
if [ -z "$ALL_CHANGED_SLUGS" ]; then
echo "No changed apps detected."
echo "CHANGED_APPS=" >> "$GITHUB_OUTPUT"
echo "HAS_CHANGES=false" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "Detected changed apps:"
echo "$ALL_CHANGED_SLUGS" | while read -r slug; do
echo " - $slug"
done
# Output as JSON array for GitHub Actions
CHANGED_APPS_JSON=$(echo "$ALL_CHANGED_SLUGS" | jq -R -s -c 'split("\n") | map(select(length > 0))')
echo "CHANGED_APPS=$CHANGED_APPS_JSON" >> "$GITHUB_OUTPUT"
echo "HAS_CHANGES=true" >> "$GITHUB_OUTPUT"
+38
View File
@@ -0,0 +1,38 @@
#!/bin/bash
# Script to filter apps.json to only include specified app slugs
# Usage: filter-apps-json.sh <slugs_json_array> <output_file>
set -euo pipefail
# Get repository root
REPO_ROOT="${GITHUB_WORKSPACE:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
APPS_JSON="${REPO_ROOT}/ee/maintained-apps/outputs/apps.json"
# Check if jq is available
if ! command -v jq &> /dev/null; then
echo "Error: jq is required but not installed" >&2
exit 1
fi
# Parse arguments
SLUGS_JSON="$1"
OUTPUT_FILE="$2"
if [ -z "$SLUGS_JSON" ] || [ "$SLUGS_JSON" == "[]" ] || [ "$SLUGS_JSON" == "null" ]; then
echo "No slugs provided, creating empty apps.json"
echo '{"version": 2, "apps": []}' > "$OUTPUT_FILE"
exit 0
fi
# Read the original apps.json
if [ ! -f "$APPS_JSON" ]; then
echo "Error: apps.json not found at $APPS_JSON" >&2
exit 1
fi
# Filter apps.json to only include the specified slugs
jq --argjson slugs "$SLUGS_JSON" '.apps = (.apps | map(select(.slug as $slug | $slugs | index($slug) != null)))' "$APPS_JSON" > "$OUTPUT_FILE"
echo "Filtered apps.json created with $(jq '.apps | length' "$OUTPUT_FILE") app(s)"