Created
June 8, 2023 04:25
-
-
Save wallentx/500e911c040b9caafe7f94eabb0adc70 to your computer and use it in GitHub Desktop.
This file contains 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
#!/usr/bin/env bash | |
set -euo pipefail | |
download_dir="." | |
TMPOUT=$(mktemp /tmp/tmpXXXXXXXXXX) | |
while getopts ":d:v" opt; do | |
case ${opt} in | |
d) | |
download_dir=$OPTARG | |
;; | |
v) | |
set -x | |
;; | |
\?) | |
echo "Invalid Option: -$OPTARG" 1>&2 | |
exit 1 | |
;; | |
:) | |
echo "Option -$OPTARG requires an argument." 1>&2 | |
exit 1 | |
;; | |
esac | |
done | |
shift $((OPTIND -1)) | |
function shutdown() { | |
tput cnorm | |
rm "$TMPOUT" | |
} | |
trap shutdown EXIT | |
function _cursorBack() { | |
echo -en "\033[$1D" | |
} | |
function _spinner() { | |
local LC_CTYPE=C | |
local LC_ALL=en_US.utf-8 | |
tput civis | |
local CL="\e[2K" | |
local spin="⣷⣯⣟⡿⢿⣻⣽⣾" | |
local pid=$(jobs -p) | |
local charwidth=1 | |
local i=0 | |
while kill -0 $pid 2>/dev/null; do | |
local i=$(((i + charwidth) % ${#spin})) | |
printf "%s" "$(tput setaf 2)${spin:i:charwidth}$(tput sgr0)" | |
_cursorBack 1 | |
sleep .1 | |
done | |
echo -ne "$CL" | |
tput cnorm | |
wait $(jobs -p) | |
} | |
Coff='\e[0m' # Off | |
Green='\e[0;32m' # Green | |
Blue='\e[0;34m' # Blue | |
Yellow='\e[0;33m' # Yellow | |
Purple='\e[0;35m' # Purple | |
BIBlack='\e[1;90m' # Bold Intense Black | |
echo -ne "${Yellow}Parsing workflows...${Coff}" | |
# Check if an array contains an element | |
function containsElement () { | |
local e match="$1" | |
shift | |
for e; do [[ "$e" == "$match" ]] && return 0; done | |
return 1 | |
} | |
# Parse the URL | |
url=$1 | |
repo_owner=$(echo "$url" | cut -d'/' -f4) | |
repo_name=$(echo "$url" | cut -d'/' -f5) | |
pr_number=$(echo "$url" | cut -d'/' -f7) | |
# Get PR details to find the branch name | |
pr_details=$(gh api repos/"$repo_owner/$repo_name/pulls/$pr_number") | |
branch_name=$(echo "$pr_details" | jq -r '.head.ref') | |
# Get the workflow runs for the PR branch | |
workflow_runs=$(gh api repos/"$repo_owner/$repo_name"/actions/runs?branch="$branch_name") | |
# Create array to store processed workflows | |
processed_workflows=() | |
# Create associative arrays to store artifact details | |
declare -A artifact_names | |
declare -A artifact_sizes | |
# Prepare a list of all relevant workflows and their artifacts | |
workflows_with_artifacts=() | |
while read -r line; do | |
# Get workflow name and run id from link | |
workflow_name=$(echo "$line" | rev | cut -d' ' -f2- | rev ) | |
run_id=$(echo "$line" | rev | cut -d' ' -f1 | rev) | |
# Skip if this workflow is already processed | |
if containsElement "$workflow_name" "${processed_workflows[@]}"; then | |
continue | |
fi | |
# Get workflow run status | |
# run_status=$(echo "$workflow_runs" | jq -r ".workflow_runs[] | select(.id == $run_id) | .status") | |
# If the run status is 'pending' or 'in_progress', inform the user | |
# if [[ "$run_status" == "pending" ]] || [[ "$run_status" == "in_progress" ]]; then | |
# echo "Warning: Workflow run $run_id is currently $run_status." | |
# fi | |
# List the artifacts for the run | |
export artifacts=$(gh api repos/"$repo_owner/$repo_name/actions/runs/$run_id"/artifacts | jq -r '.artifacts[] | .name') | |
# Only count this workflow if it has at least one artifact | |
if [ "$artifacts" != "" ]; then | |
workflows_with_artifacts+=("$workflow_name#$run_id") | |
processed_workflows+=("$workflow_name") | |
fi | |
done < <(echo "$workflow_runs" | jq -r '.workflow_runs[] | select(.name != null) | "\(.name) \(.id)"' | sort -r) | |
#done < <(echo "$workflow_runs" | jq -r '.workflow_runs[] | select(.name != null) and (.status != "in_progress") and (.status != "queued") | "\(.name) \(.id)"' | sort -r) | |
# Count the total number of workflows with artifacts | |
total_workflows=${#workflows_with_artifacts[@]} | |
# Iterate over each workflow with artifacts | |
printf '\r' | |
echo -e "${Blue}Artifacts for PR${Green} #${Purple}$pr_number${Coff}:" | |
current_workflow=1 | |
for workflow_with_artifact in "${workflows_with_artifacts[@]}"; do | |
# Get workflow name and run id from line | |
export workflow_name=$(echo "$workflow_with_artifact" | cut -d'#' -f1) | |
export run_id=$(echo "$workflow_with_artifact" | cut -d'#' -f2) | |
# List the artifacts for the run | |
export artifacts=$(gh api repos/"$repo_owner/$repo_name/actions/runs/$run_id"/artifacts) | |
# Check if we're at the last workflow | |
if [[ $current_workflow -eq $total_workflows ]]; then | |
echo -e "└──${BIBlack}$workflow_name:${Coff}" | |
else | |
echo -e "├──${BIBlack}$workflow_name:${Coff}" | |
fi | |
# Iterate over artifacts and echo name | |
while read -r artifact; do | |
name=$(echo "$artifact" | jq -r '.name') | |
size=$(echo "$artifact" | jq -r '.size_in_bytes') | |
download_url=$(echo "$artifact" | jq -r '.archive_download_url') | |
artifact_names[$name]=$download_url | |
artifact_sizes[$name]=$size | |
if [[ $current_workflow -eq $total_workflows ]]; then | |
echo " └──📦$name" | |
else | |
echo "│ └──📦$name" | |
fi | |
done < <(echo "$artifacts" | jq -c '.artifacts[]') | |
if [[ $current_workflow -ne $total_workflows ]]; then | |
echo "│" | |
fi | |
# Increment the current workflow counter | |
current_workflow=$((current_workflow + 1)) | |
done | |
function getArtifact() { | |
gh \ | |
api \ | |
-H "Accept: application/vnd.github+json" \ | |
-H "X-GitHub-Api-Version: 2022-11-28" \ | |
"$download_url" > "$download_dir/$artifact_name.zip" | |
} | |
function execInfo() { | |
getArtifact >"$TMPOUT" & | |
_spinner | |
echo -ne "\r" | |
cat "$TMPOUT" | |
} | |
function select_artifacts() { | |
local artifact_names_list=("$@") | |
local num_artifacts=${#artifact_names_list[@]} | |
local selected_artifacts=() | |
if [[ $num_artifacts -eq 0 ]]; then | |
echo "No artifacts" | |
exit 0 | |
fi | |
echo " | |
" | |
echo -e "${Green}== Artifacts to download ==${Coff}" | |
for ((i=0; i<num_artifacts; i++)); do | |
echo -e "${Purple}$((i+1)) ${Yellow}${artifact_names_list[i]}${Coff}" | |
done | |
echo -e "${Green}==> ${Blue}Enter the numbers of the artifacts you want to download ${Yellow}(e.g., '1 2 3', '1-3' or '^4')${Coff}" | |
echo -ne "${Green}==>${Coff}" | |
read -rp " " input | |
if [[ $input == *'-'* ]]; then | |
IFS='-' read -ra RANGE <<< "$input" | |
for ((i=RANGE[0]; i<=RANGE[1]; i++)); do | |
selected_artifacts+=("${artifact_names_list[i-1]}") | |
done | |
elif [[ $input == *'^'* ]]; then | |
IFS='^' read -ra EXCLUDE <<< "$input" | |
for ((i=1; i<=num_artifacts; i++)); do | |
if [[ $i != "${EXCLUDE[1]}" ]]; then | |
selected_artifacts+=("${artifact_names_list[i-1]}") | |
fi | |
done | |
else | |
# shellcheck disable=SC2068 | |
for i in ${input[@]}; do | |
selected_artifacts+=("${artifact_names_list[i-1]}") | |
done | |
fi | |
# Download selected artifacts | |
for artifact in "${selected_artifacts[@]}"; do | |
artifact_name=$(echo "$artifact" | cut -d' ' -f1) | |
download_url="${artifact_names[$artifact_name]}" | |
echo -ne "${Blue}Downloading ${Yellow}$artifact_name.zip${Coff}... " | |
execInfo | |
echo -e "${Blue}Download complete!${Coff}" | |
done | |
} | |
# Populate an array of artifacts | |
artifact_list=() | |
for artifact_name in "${!artifact_names[@]}"; do | |
artifact_size_bytes=${artifact_sizes[$artifact_name]} | |
artifact_list+=("$artifact_name ($(echo "$artifact_size_bytes" | awk '{ byte =$1 /1024/1024; print byte " MB" }'))") | |
done | |
select_artifacts "${artifact_list[@]}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment