@@ -740,7 +740,8 @@ def diff_approved_vs_new(
740740
741741
742742DOCKERFILE_TEMPLATE = """\
743- FROM node:20-slim
743+ ARG NODE_VERSION=20
744+ FROM node:${NODE_VERSION}-slim
744745
745746RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
746747RUN corepack enable
@@ -873,9 +874,42 @@ def diff_approved_vs_new(
873874"""
874875
875876
877+ def detect_node_version (
878+ org : str , repo : str , commit_hash : str , sub_path : str = "" ,
879+ gh : GitHubClient | None = None ,
880+ ) -> str :
881+ """Detect the Node.js major version from the action's using: field.
882+
883+ Fetches action.yml from GitHub at the given commit and extracts the
884+ node version (e.g. 'node20' -> '20'). Falls back to '20' if detection fails.
885+ """
886+ # Try action.yml then action.yaml, in sub_path first if given
887+ candidates = []
888+ if sub_path :
889+ candidates .extend ([f"{ sub_path } /action.yml" , f"{ sub_path } /action.yaml" ])
890+ candidates .extend (["action.yml" , "action.yaml" ])
891+
892+ for path in candidates :
893+ url = f"https://raw.githubusercontent.com/{ org } /{ repo } /{ commit_hash } /{ path } "
894+ try :
895+ resp = requests .get (url , timeout = 10 )
896+ if not resp .ok :
897+ continue
898+ for line in resp .text .splitlines ():
899+ match = re .match (r"\s+using:\s*['\"]?(node\d+)['\"]?" , line )
900+ if match :
901+ version = match .group (1 ).replace ("node" , "" )
902+ return version
903+ except requests .RequestException :
904+ continue
905+
906+ return "20"
907+
908+
876909def build_in_docker (
877910 org : str , repo : str , commit_hash : str , work_dir : Path ,
878911 sub_path : str = "" ,
912+ gh : GitHubClient | None = None ,
879913) -> tuple [Path , Path , str , str ]:
880914 """Build the action in a Docker container and extract original + rebuilt dist.
881915
@@ -909,6 +943,11 @@ def build_in_docker(
909943 console .print ()
910944 console .print (Panel (info_table , title = "Action Build Verification" , border_style = "blue" ))
911945
946+ # Detect Node.js version from action.yml before building
947+ node_version = detect_node_version (org , repo , commit_hash , sub_path , gh = gh )
948+ if node_version != "20" :
949+ console .print (f" [green]✓[/green] Detected Node.js version: [bold]node{ node_version } [/bold]" )
950+
912951 with console .status ("[bold blue]Building Docker image...[/bold blue]" ) as status :
913952 # Build Docker image
914953 status .update ("[bold blue]Cloning repository and building action...[/bold blue]" )
@@ -917,6 +956,8 @@ def build_in_docker(
917956 "docker" ,
918957 "build" ,
919958 "--build-arg" ,
959+ f"NODE_VERSION={ node_version } " ,
960+ "--build-arg" ,
920961 f"REPO_URL={ repo_url } " ,
921962 "--build-arg" ,
922963 f"COMMIT_HASH={ commit_hash } " ,
@@ -1237,7 +1278,7 @@ def verify_single_action(action_ref: str, gh: GitHubClient | None = None, ci_mod
12371278 with tempfile .TemporaryDirectory (prefix = "verify-action-" ) as tmp :
12381279 work_dir = Path (tmp )
12391280 original_dir , rebuilt_dir , action_type , out_dir_name = build_in_docker (
1240- org , repo , commit_hash , work_dir , sub_path = sub_path ,
1281+ org , repo , commit_hash , work_dir , sub_path = sub_path , gh = gh ,
12411282 )
12421283
12431284 # Non-JavaScript actions (docker, composite) don't have compiled JS to verify
@@ -1305,7 +1346,8 @@ def extract_action_refs_from_pr(pr_number: int, gh: GitHubClient | None = None)
13051346 refs : list [str ] = []
13061347 for line in diff_text .splitlines ():
13071348 # Match lines like: + - uses: org/repo/sub@hash # tag
1308- match = re .search (r"^\+.*uses:\s+([^@\s]+)@([0-9a-f]{40})" , line )
1349+ # Also match 'use:' (common typo for 'uses:')
1350+ match = re .search (r"^\+.*uses?:\s+([^@\s]+)@([0-9a-f]{40})" , line )
13091351 if match :
13101352 action_path = match .group (1 )
13111353 commit_hash = match .group (2 )
0 commit comments