true, 'check_composer' => true, 'check_upm' => false ) ); gitea_check_repo($auth_token, $gitea_url, 'bit/skeletor', array( 'check_forks' => true, 'check_composer' => true, 'check_upm' => true ) ); gitea_check_repo($auth_token, $gitea_url, 'bit/skeletor-rnd', array( 'check_forks' => true, 'check_composer' => true, 'check_upm' => true ) ); gitea_check_repo($auth_token, $gitea_url, 'game/gymmania', array( 'check_forks' => false, 'check_composer' => true, 'check_upm' => false ) ); ////////////////////////////////// function gitea_login($gitea_url, $user, $pass) { $token_field = "test_".time(); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://git.bit5.ru/api/v1/users/$user/tokens"); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(array("name" => $token_field))); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); curl_setopt($ch, CURLOPT_USERPWD, $user . ":" . $pass); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); $json = curl_exec($ch); curl_close($ch); $res = json_decode($json, true); if(!isset($res['sha1'])) throw new Exception("Could not login to gitea"); return $res['sha1']; } function gitea_api_call($auth_token, $gitea_url, $api_path) { $api_url = "$gitea_url/api/v1/$api_path"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $api_url); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Accept: application/json', "Authorization: token $auth_token" ) ); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); $response = curl_exec($ch); $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $header = substr($response, 0, $header_size); $json = substr($response, $header_size); $info = curl_getinfo($ch); curl_close($ch); if($info['http_code'] != 200) return $info['http_code']; return json_decode($json, true); } function gitea_get_tags($auth_token, $gitea_url, $repo) { $res = gitea_api_call($auth_token, $gitea_url, "repos/$repo/tags"); if($res === 404) return array(); else if(is_numeric($res)) throw new Exception("Bad response: $res"); return $res; } function gitea_get_source($auth_token, $gitea_url, $repo, $path) { $res = gitea_api_call($auth_token, $gitea_url, "repos/$repo/contents/$path"); if(is_numeric($res)) throw new Exception("Bad response: $res"); if(!isset($res['content'])) throw new Exception("Could not get file at path '$path'"); return base64_decode($res['content']); } function gitea_get_forks($auth_token, $gitea_url, $repo) { $res = gitea_api_call($auth_token, $gitea_url, "repos/$repo/forks"); if(is_numeric($res)) throw new Exception("Bad response: $res"); return $res; } function gitea_get_commits($auth_token, $gitea_url, $repo) { $res = gitea_api_call($auth_token, $gitea_url, "repos/$repo/commits"); if(is_numeric($res)) throw new Exception("Bad response: $res"); return $res; } function gitea_get_commit($auth_token, $gitea_url, $repo, $sha) { $res = gitea_api_call($auth_token, $gitea_url, "repos/$repo/git/commits/$sha"); if($res === 404) return null; else if(is_numeric($res)) throw new Exception("Bad response: $res"); else return $res; } function github_get_tags($github_repo) { $api_url = "https://api.github.com/repos/$github_repo/tags"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $api_url); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_USERAGENT, "test"); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); $response = curl_exec($ch); $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $header = substr($response, 0, $header_size); $json = substr($response, $header_size); $info = curl_getinfo($ch); curl_close($ch); if($info['http_code'] != 200) return $info['http_code']; return json_decode($json, true); } function _is_composer_git_repo(array $repos, $repo) { foreach($repos as $item) { if($item['type'] == 'git' && $item['url'] == $repo) return true; } return false; } function _is_composer_github_package(array $repos, $repo, &$github_repo) { foreach($repos as $item) { if($item['type'] == 'package' && $item['package']['name'] == $repo && preg_match('~https?://github.com/([^/]+)/([^/]+)~', $item['package']['dist']['url'], $matches)) { $github_repo = $matches[1].'/'.$matches[2]; return true; } } return false; } function gitea_check_repo( $auth_token, $gitea_url, $base_repo, array $opts ) { echo "************************* Checking repo '$base_repo' *************************\n"; $commits = gitea_get_commits($auth_token, $gitea_url, $base_repo); if($opts['check_forks']) { $forks = gitea_get_forks($auth_token, $gitea_url, $base_repo); $behind_forks = array(); echo "== Checking forks ==\n"; foreach($forks as $fork) { $repo_fork = $fork['full_name']; foreach($commits as $commit) { $status = gitea_get_commit($auth_token, $gitea_url, $repo_fork, $commit['sha']); if($status === null) { $behind_forks[] = $repo_fork; break; } //early exit if commit exists else if(isset($status['sha'])) { break; } } } echo "Behind forks: " . implode(", ", $behind_forks) . "\n"; } if($opts['check_composer']) { echo "== Checking Composer manifest ==\n"; $composer_json = gitea_get_source($auth_token, $gitea_url, $base_repo, "composer/composer.json"); $composer_arr = json_decode($composer_json, true); foreach($composer_arr['require'] as $repo => $version) { if(strpos($repo, "bit/") !== 0) continue; if(_is_composer_git_repo($composer_arr['repositories'], "$gitea_url/$repo")) { $tags = gitea_get_tags($auth_token, $gitea_url, $repo); if(isset($tags[0])) { $last_tag_info = $tags[0]; if(ltrim($last_tag_info["name"], 'v') != ltrim($version, 'v')) echo "Package '$repo': current $version, latest {$last_tag_info["name"]}\n"; } else echo "Could not fetch tags for $repo\n"; } else if(_is_composer_github_package($composer_arr['repositories'], $repo, $github_repo)) { $tags = github_get_tags($github_repo); if(isset($tags[0])) { $last_tag_info = $tags[0]; if(ltrim($last_tag_info["name"], 'v') != ltrim($version, 'v')) echo "Package '$repo': current $version, latest {$last_tag_info["name"]}\n"; } } } } if($opts['check_upm']) { echo "== Checking UPM manifest ==\n"; $upm_json = gitea_get_source($auth_token, $gitea_url, $base_repo, "unity/Packages/manifest.json"); $upm_arr = json_decode($upm_json, true); foreach($upm_arr['dependencies'] as $name => $version) { if(strpos($name, "com.bitgames.") !== 0) continue; $name = str_replace("com.bitgames.ecs", "com.bitgames.leoecs", $name); $name = str_replace("com.bitgames.", "", $name); $name = str_replace(".", "-", $name); $repo = 'bit-upm/' . $name; $tags = gitea_get_tags($auth_token, $gitea_url, $repo); if(isset($tags[0])) { $last_tag_info = $tags[0]; if(ltrim($last_tag_info["name"], 'v') != ltrim($version, 'v')) echo "Package '$repo': current $version, latest {$last_tag_info["name"]}\n"; } else echo "Could not fetch tags for $repo\n"; } } }