#!/usr/bin/env bash # Migrate GitHub Actions in workflow files to use mirrored actions # Usage: ./migrate-actions.sh set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ACTIONS_LIST="${SCRIPT_DIR}/actions-to-mirror.txt" if [[ $# -lt 1 ]]; then echo "Usage: $0 " echo "Example: $0 /path/to/repo" exit 1 fi REPO_PATH="$1" if [[ ! -d "$REPO_PATH" ]]; then echo "Error: Repository path not found: $REPO_PATH" exit 1 fi if [[ ! -f "$ACTIONS_LIST" ]]; then echo "Error: Actions list not found at $ACTIONS_LIST" exit 1 fi # Build lookup table of mirrored actions declare -A MIRRORED_ACTIONS while IFS= read -r line || [[ -n "$line" ]]; do [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue line="$(echo "$line" | xargs)" # Store as key for quick lookup (e.g., "actions/checkout@v4") MIRRORED_ACTIONS["$line"]=1 done < "$ACTIONS_LIST" # Find workflow files WORKFLOW_DIR="${REPO_PATH}/.github/workflows" if [[ ! -d "$WORKFLOW_DIR" ]]; then echo "Error: No .github/workflows directory found in $REPO_PATH" exit 1 fi # Track unmirrored actions declare -A UNMIRRORED_ACTIONS # Convert action reference to mirrored path # e.g., "actions/checkout@v4" -> "infrastructure/actions/actions/checkout-v4" convert_action() { local action="$1" local org repo version # Parse org/repo@version org="${action%%/*}" local repo_version="${action#*/}" repo="${repo_version%%@*}" version="${repo_version#*@}" echo "infrastructure/actions/${org}/${repo}-${version}" } # Process a single workflow file process_workflow() { local file="$1" local modified=false local temp_file temp_file=$(mktemp) while IFS= read -r line || [[ -n "$line" ]]; do # Check if line contains a uses: statement if [[ "$line" =~ ^([[:space:]]*)uses:[[:space:]]*([^[:space:]]+) ]]; then local indent="${BASH_REMATCH[1]}" local action="${BASH_REMATCH[2]}" # Remove quotes if present action="${action#\"}" action="${action%\"}" action="${action#\'}" action="${action%\'}" # Check if this is a GitHub action reference (org/repo@version format) if [[ "$action" =~ ^[a-zA-Z0-9_-]+/[a-zA-Z0-9_.-]+@[a-zA-Z0-9._-]+$ ]]; then if [[ -n "${MIRRORED_ACTIONS[$action]:-}" ]]; then # Replace with mirrored version local new_action new_action=$(convert_action "$action") echo "${indent}uses: ${new_action}" >> "$temp_file" modified=true echo " Replaced: $action -> $new_action" else # Not in our mirror list UNMIRRORED_ACTIONS["$action"]+="${file##*/} " echo "$line" >> "$temp_file" fi else # Not a standard action reference (could be local action, docker, etc.) echo "$line" >> "$temp_file" fi else echo "$line" >> "$temp_file" fi done < "$file" if [[ "$modified" == true ]]; then cp "$temp_file" "$file" echo " Updated: $file" fi rm -f "$temp_file" } echo "Migrating workflows in: $REPO_PATH" echo "Using actions list: $ACTIONS_LIST" echo "" # Process all workflow files for workflow in "$WORKFLOW_DIR"/*.yml "$WORKFLOW_DIR"/*.yaml; do [[ -f "$workflow" ]] || continue echo "Processing: ${workflow##*/}" process_workflow "$workflow" echo "" done # Report unmirrored actions if [[ ${#UNMIRRORED_ACTIONS[@]} -gt 0 ]]; then echo "========================================" echo "UNMIRRORED ACTIONS (not replaced):" echo "========================================" for action in "${!UNMIRRORED_ACTIONS[@]}"; do echo "" echo " $action" echo " Used in: ${UNMIRRORED_ACTIONS[$action]}" done echo "" echo "Add these to $ACTIONS_LIST and re-run clone-actions.sh to mirror them." fi echo "" echo "Migration complete."