* Go for Broke * Let it fire * Add PipLine * Create the dir if it doesn't exist * Install Setuptools * Track Test Action's files * Fix Calling Job * Track Build Action files * Install Distutils, rename filenames * Fix Fail conditions * Make Build scripts smarter * Add file * Concat DLLs lists * Try to fail if Error DLLs * Try to make the fail smarter * Moar verbosity * Print the stuff first * Print outputs objects * See if this skips failure * Use py instead * Print error list * Don't ValueError * Try checking a different way * Try something else * Bleh, spell filename correctly * Update excluded_dlls.json * Ugh, gotta compare old to new somehow * Compare to old list * Condense build script * Moar verbosity * Update the global version * Update Excluded DLLs list * Actually use the bad DLLs list * Make a version number * Fix version number building * Fix version number building again * Fix Diagnostics * Try REST API stuff * Try REST API again * Moar REST * await * Get SHA * Try it all together * Del test workflow * Add Perms * Use a Token * Try this Token * Try different Token * Try different Token * Create App Version earlier * See this error again * Don't fail if App Version not made yet * Use New Secret * Print whole response * Documentation for Tagger * Update CI Instructions * Update CI * List References * Find latest tag Fix App Version getter * Fix commas * Check returned data * Update Build Script * Fix substring * Fix Git tag * Fix tag again * Visual indicators * Use encoding * Remove an indicator * Update CI * Update Project Name * PyInstaller Spec Template file * Update Build Script * Fix Tagger * Update CI * Download AppVersion during build * Test job can fail * Upload Logs instead of printing them * Change from Reusable Workflow to Action * Change ref to token * Compare to string * Use PAT * Use String literal * Remove Reusable Workflow * Update CI Scripts * Go for Broke * Let it fire * Add PipLine * Create the dir if it doesn't exist * Install Setuptools * Track Test Action's files * Fix Calling Job * Track Build Action files * Install Distutils, rename filenames * Fix Fail conditions * Make Build scripts smarter * Add file * Concat DLLs lists * Try to fail if Error DLLs * Try to make the fail smarter * Moar verbosity * Print the stuff first * Print outputs objects * See if this skips failure * Use py instead * Print error list * Don't ValueError * Try checking a different way * Try something else * Bleh, spell filename correctly * Update excluded_dlls.json * Ugh, gotta compare old to new somehow * Compare to old list * Condense build script * Moar verbosity * Update the global version * Update Excluded DLLs list * Actually use the bad DLLs list * Make a version number * Fix version number building * Fix version number building again * Fix Diagnostics * Try REST API stuff * Try REST API again * Moar REST * await * Get SHA * Try it all together * Del test workflow * Add Perms * Use a Token * Try this Token * Try different Token * Try different Token * Create App Version earlier * See this error again * Don't fail if App Version not made yet * Use New Secret * Print whole response * Documentation for Tagger * Update CI Instructions * Update CI * List References * Find latest tag Fix App Version getter * Fix commas * Check returned data * Update Build Script * Fix substring * Fix Git tag * Fix tag again * Visual indicators * Use encoding * Remove an indicator * Update CI * Update Project Name * PyInstaller Spec Template file * Update Build Script * Fix Tagger * Update CI * Download AppVersion during build * Test job can fail * Upload Logs instead of printing them * Change from Reusable Workflow to Action * Change ref to token * Compare to string * Use PAT * Use String literal * Remove Reusable Workflow * Update CI Scripts --------- Co-authored-by: Minnie A. Trethewey (Mike) <minnietrethewey@gmail.com>
169 lines
5.7 KiB
Python
169 lines
5.7 KiB
Python
# pylint: disable=invalid-name
|
|
'''
|
|
List GitHub Actions versions used and latest versions
|
|
'''
|
|
import json
|
|
import os
|
|
import ssl
|
|
import urllib.request
|
|
import yaml
|
|
from json.decoder import JSONDecodeError
|
|
|
|
allACTIONS = {}
|
|
listACTIONS = []
|
|
|
|
VER_WIDTH = 10
|
|
NAME_WIDTH = 40
|
|
LINE_WIDTH = 1 + NAME_WIDTH + 5 + VER_WIDTH + 5 + VER_WIDTH + 1
|
|
|
|
def process_walk(key, node):
|
|
'''
|
|
Process walking through the array
|
|
'''
|
|
global allACTIONS
|
|
global listACTIONS
|
|
if key == "uses":
|
|
action = node.split('@')
|
|
version = ""
|
|
if '@' in node:
|
|
version = action[1]
|
|
action = action[0]
|
|
if action not in allACTIONS:
|
|
allACTIONS[action] = {
|
|
"versions": [],
|
|
"latest": ""
|
|
}
|
|
allACTIONS[action]["versions"].append(version)
|
|
allACTIONS[action]["versions"] = list(
|
|
set(
|
|
allACTIONS[action]["versions"]
|
|
)
|
|
)
|
|
listACTIONS.append(node)
|
|
|
|
|
|
def walk(key, node):
|
|
'''
|
|
How to walk through the array
|
|
'''
|
|
if isinstance(node, dict):
|
|
return {k: walk(k, v) for k, v in node.items()}
|
|
elif isinstance(node, list):
|
|
return [walk(key, x) for x in node]
|
|
else:
|
|
return process_walk(key, node)
|
|
|
|
|
|
for r, d, f in os.walk(os.path.join(".", ".github")):
|
|
if "actions" in r or "workflows" in r:
|
|
for filename in f:
|
|
# if it's not a YAML or it's turned off, skip it
|
|
if (".yml" not in filename and ".yaml" not in filename) or (".off" in filename):
|
|
continue
|
|
listACTIONS = []
|
|
# print filename
|
|
filename_line = "-" * (len(os.path.join(r, filename)) + 2)
|
|
print(
|
|
" " +
|
|
filename_line +
|
|
" "
|
|
)
|
|
print("| " + os.path.join(r, filename) + " |")
|
|
# read the file
|
|
with(open(os.path.join(r, filename), "r", encoding="utf-8")) as yamlFile:
|
|
print(
|
|
"|" +
|
|
filename_line +
|
|
"-" +
|
|
("-" * (LINE_WIDTH - len(filename_line) + 1)) +
|
|
" "
|
|
)
|
|
yml = yaml.safe_load(yamlFile)
|
|
walk("uses", yml)
|
|
dictACTIONS = {}
|
|
for k in sorted(list(set(listACTIONS))):
|
|
action = k.split('@')[0]
|
|
version = k.split('@')[1] if '@' in k else ""
|
|
latest = ""
|
|
# if it's not a location action, get the latest version number
|
|
if "./." not in action:
|
|
apiURL = f"https://api.github.com/repos/{action}/releases/latest"
|
|
if True:
|
|
apiReq = None
|
|
try:
|
|
apiReq = urllib.request.urlopen(
|
|
apiURL,
|
|
context=ssl._create_unverified_context()
|
|
)
|
|
except urllib.error.HTTPError as e:
|
|
if e.code != 403:
|
|
print(e.code, apiURL)
|
|
if apiReq:
|
|
apiRes = {}
|
|
try:
|
|
apiRes = json.loads(
|
|
apiReq.read().decode("utf-8"))
|
|
except JSONDecodeError as e:
|
|
raise ValueError("🔴API Request failed: " + apiURL)
|
|
if apiRes:
|
|
latest = apiRes["tag_name"] if "tag_name" in apiRes else ""
|
|
if latest != "":
|
|
allACTIONS[action]["latest"] = latest
|
|
dictACTIONS[action] = version
|
|
# print action name and version info
|
|
for action, version in dictACTIONS.items():
|
|
print(
|
|
"| " + \
|
|
f"{action.ljust(NAME_WIDTH)}" + \
|
|
"\t" + \
|
|
f"{(version or 'N/A').ljust(VER_WIDTH)}" + \
|
|
"\t" + \
|
|
f"{(allACTIONS[action]['latest'] or 'N/A').ljust(VER_WIDTH)}" + \
|
|
" |"
|
|
)
|
|
print(
|
|
" " +
|
|
("-" * (LINE_WIDTH + 2)) +
|
|
" "
|
|
)
|
|
print("")
|
|
|
|
# print outdated versions summary
|
|
first = True
|
|
outdated = False
|
|
for action, actionData in allACTIONS.items():
|
|
if len(actionData["versions"]) > 0:
|
|
if actionData["latest"] != "" and actionData["versions"][0] != actionData["latest"]:
|
|
outdated = True
|
|
if first:
|
|
first = False
|
|
filename_line = "-" * (len("| Outdated |"))
|
|
print(
|
|
" " +
|
|
filename_line +
|
|
" "
|
|
)
|
|
print("| 🔴Outdated |")
|
|
print(
|
|
"|" +
|
|
filename_line +
|
|
"-" +
|
|
("-" * (LINE_WIDTH - len(filename_line) + 1)) +
|
|
" "
|
|
)
|
|
print(
|
|
"| " + \
|
|
f"{action.ljust(40)}" + \
|
|
"\t" + \
|
|
f"{(','.join(actionData['versions']) or 'N/A').ljust(10)}" + \
|
|
"\t" + \
|
|
f"{actionData['latest'].ljust(10)}" + \
|
|
" |"
|
|
)
|
|
if outdated:
|
|
print(
|
|
" " +
|
|
("-" * (LINE_WIDTH + 2)) +
|
|
" "
|
|
)
|