.mise/tasks/check-actions-updates
.mise/tasks/check-actions-updatesBrowse 1970 files
1,611 tokens
4,941 bytes
Token encoding: o200k_base
Snapshot 21a254f
← Back to SKILL.md
1#!/usr/bin/env zsh2# Description: check and interactively update all used GitHub Actions.3# Matches both SHA-pinned (@sha) and tag-pinned (@v3) actions.4 5set -euo pipefail6 7typeset -g c_reset c_bold c_dim c_green c_yellow c_red c_cyan c_blue8 9init_colors() {10 if [[ -t 1 ]] && [[ -z "${NO_COLOR:-}" ]] && [[ "${TERM:-}" != "dumb" ]]; then11 autoload -U colors && colors12 c_reset=$reset_color13 c_bold=$bold_color14 c_dim=$'\e[2m'15 c_green=$fg[green]16 c_yellow=$fg[yellow]17 c_red=$fg[red]18 c_cyan=$fg[cyan]19 c_blue=$fg[blue]20 else21 c_reset=''22 c_bold=''23 c_dim=''24 c_green=''25 c_yellow=''26 c_red=''27 c_cyan=''28 c_blue=''29 fi30}31 32print_rule() {33 echo "${c_dim}────────────────────────────────────────────────────────${c_reset}"34}35 36format_ref() {37 local ref=$138 if [[ ${#ref} -ge 40 ]] && [[ "$ref" =~ ^[0-9a-fA-F]+$ ]]; then39 echo "${ref:0:7}…"40 else41 echo "$ref"42 fi43}44 45prompt_update() {46 local repo=$1 ref=$2 latest_sha=$347 if [[ -t 0 ]] && [[ -r /dev/tty ]]; then48 echo -n " ${c_bold}Update${c_reset} ${c_dim}@${ref}${c_reset} ${c_dim}→${c_reset} ${c_cyan}@${latest_sha}${c_reset}? ${c_dim}(y/N)${c_reset} "49 read -k 1 choice < /dev/tty50 echo51 [[ "$choice" == "y" || "$choice" == "Y" ]]52 else53 echo " ${c_dim}(non-interactive: skipped — run in a terminal to apply)${c_reset}"54 return 155 fi56}57 58init_colors59 60repo_root="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"61cd "$repo_root"62 63all_actions=$(grep -rE "uses: [^@]+@[^[:space:]]+" .github/workflows 2>/dev/null \64 | sed -E 's/.*uses: ([^@]+)@([^[:space:]]+)/\1@\2/' \65 | sort -u)66 67if [[ -z "$all_actions" ]]; then68 echo "${c_yellow}No GitHub Action usages found in .github/workflows.${c_reset}"69 exit 070fi71 72action_count=$(echo "$all_actions" | wc -l | tr -d ' ')73repo_count=$(echo "$all_actions" | cut -d'@' -f1 | sort -u | wc -l | tr -d ' ')74 75echo "${c_bold}GitHub Actions update check${c_reset}"76echo "${c_dim}${repo_count} action(s), ${action_count} pin(s) in .github/workflows/${c_reset}"77echo78 79typeset -i count_ok=0 count_update=0 count_updated=0 count_skipped=0 count_error=080 81repos=$(echo "$all_actions" | cut -d'@' -f1 | sort -u)82 83for repo in ${(f)repos}; do84 print_rule85 echo "${c_bold}${c_cyan}${repo}${c_reset}"86 87 latest_tag=$(gh release view --repo "$repo" --json tagName --jq .tagName 2>/dev/null || true)88 if [[ -z "$latest_tag" ]]; then89 latest_tag=$(gh api "repos/$repo/tags" --jq '.[0].name' 2>/dev/null || true)90 fi91 92 if [[ -z "$latest_tag" ]]; then93 echo " ${c_red}✗${c_reset} Could not find releases or tags"94 count_error=$(( count_error + 1 ))95 echo96 continue97 fi98 99 latest_sha=$(gh api "repos/$repo/commits/$latest_tag" --header 'Accept: application/vnd.github.sha' 2>/dev/null || true)100 101 if [[ -z "$latest_sha" ]]; then102 echo " ${c_dim}Latest tag${c_reset} ${c_bold}${latest_tag}${c_reset}"103 echo " ${c_red}✗${c_reset} Could not resolve SHA for ${latest_tag}"104 count_error=$(( count_error + 1 ))105 echo106 continue107 fi108 109 echo " ${c_dim}Latest${c_reset} ${c_bold}${latest_tag}${c_reset} ${c_dim}→${c_reset} ${c_blue}$(format_ref "$latest_sha")${c_reset}"110 echo " ${c_dim}${latest_sha}${c_reset}"111 echo112 113 current_refs=$(echo "$all_actions" | grep "^$repo@" | cut -d'@' -f2)114 for ref in ${(f)current_refs}; do115 local_label="$(format_ref "$ref")"116 if [[ "$ref" == "$latest_sha" ]]; then117 printf " ${c_green}✓${c_reset} %-12s ${c_green}up to date${c_reset}\n" "@${local_label}"118 count_ok=$(( count_ok + 1 ))119 else120 printf " ${c_yellow}↑${c_reset} %-12s ${c_yellow}update available${c_reset}\n" "@${local_label}"121 echo " ${c_dim}https://github.com/${repo}/compare/${ref}...${latest_sha}${c_reset}"122 count_update=$(( count_update + 1 ))123 124 if prompt_update "$repo" "$ref" "$latest_sha"; then125 perl -i -pe "s|uses: $repo\@$ref\b|uses: $repo\@$latest_sha|g" .github/workflows/*.yml126 echo " ${c_green}✓${c_reset} Updated workflow files"127 count_updated=$(( count_updated + 1 ))128 elif [[ -t 0 ]] && [[ -r /dev/tty ]]; then129 echo " ${c_dim}⊘${c_reset} Skipped"130 count_skipped=$(( count_skipped + 1 ))131 else132 count_skipped=$(( count_skipped + 1 ))133 fi134 fi135 done136 echo137done138 139print_rule140echo "${c_bold}Summary${c_reset}"141echo " ${c_green}✓${c_reset} ${count_ok} up to date"142if (( count_update > 0 )); then143 echo " ${c_yellow}↑${c_reset} ${count_update} update(s) available"144fi145if (( count_updated > 0 )); then146 echo " ${c_green}✓${c_reset} ${count_updated} applied"147fi148if (( count_skipped > 0 )); then149 echo " ${c_dim}⊘${c_reset} ${count_skipped} skipped"150fi151if (( count_error > 0 )); then152 echo " ${c_red}✗${c_reset} ${count_error} error(s)"153fi154echo155