{"id":112531,"date":"2026-07-16T14:44:17","date_gmt":"2026-07-16T11:14:17","guid":{"rendered":"https:\/\/nabfollower.com\/blog\/%d8%a8%d8%a7-github-actions-%db%8c%da%a9-%d8%a8%d8%a7%d8%b2%d8%a8%db%8c%d9%86%db%8c-%da%a9%d9%86%d9%86%d8%af%d9%87-ai-pr-%d8%b3%d9%81%d8%a7%d8%b1%d8%b4%db%8c-%d8%a7%d8%b2-%d8%a7%d8%a8%d8%aa%d8%af\/"},"modified":"2026-07-16T14:44:17","modified_gmt":"2026-07-16T11:14:17","slug":"%d8%a8%d8%a7-github-actions-%db%8c%da%a9-%d8%a8%d8%a7%d8%b2%d8%a8%db%8c%d9%86%db%8c-%da%a9%d9%86%d9%86%d8%af%d9%87-ai-pr-%d8%b3%d9%81%d8%a7%d8%b1%d8%b4%db%8c-%d8%a7%d8%b2-%d8%a7%d8%a8%d8%aa%d8%af","status":"publish","type":"post","link":"https:\/\/nabfollower.com\/blog\/%d8%a8%d8%a7-github-actions-%db%8c%da%a9-%d8%a8%d8%a7%d8%b2%d8%a8%db%8c%d9%86%db%8c-%da%a9%d9%86%d9%86%d8%af%d9%87-ai-pr-%d8%b3%d9%81%d8%a7%d8%b1%d8%b4%db%8c-%d8%a7%d8%b2-%d8%a7%d8%a8%d8%aa%d8%af\/","title":{"rendered":"\u0628\u0627 GitHub Actions \u06cc\u06a9 \u0628\u0627\u0632\u0628\u06cc\u0646\u06cc \u06a9\u0646\u0646\u062f\u0647 AI PR \u0633\u0641\u0627\u0631\u0634\u06cc \u0627\u0632 \u0627\u0628\u062a\u062f\u0627 \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f"},"content":{"rendered":"<p><strong>\u0633\u0627\u062e\u062a \u0645\u0631\u0648\u0631\u06af\u0631 \u06a9\u062f \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0633\u0641\u0627\u0631\u0634\u06cc \u0628\u0627 Gemini \u062f\u0631 GitHub Actions<\/strong><\/p>\n<p>\u0627\u06cc\u0646 \u0645\u0642\u0627\u0644\u0647 \u0631\u0627\u0647\u0646\u0645\u0627\u06cc \u0633\u0627\u062e\u062a \u06cc\u06a9 \u0631\u0628\u0627\u062a \u0645\u0631\u0648\u0631\u06af\u0631 \u06a9\u062f (Code Reviewer) \u062e\u0648\u062f\u06a9\u0627\u0631\u060c \u0633\u0628\u06a9\u200c\u0648\u0632\u0646 \u0648 \u0628\u062f\u0648\u0646 \u0648\u0627\u0628\u0633\u062a\u06af\u06cc \u0628\u0647 \u0633\u0631\u0648\u06cc\u0633\u200c\u0647\u0627\u06cc \u0634\u062e\u0635 \u062b\u0627\u0644\u062b (\u0645\u0627\u0646\u0646\u062f CodeRabbit \u06cc\u0627 Copilot) \u0627\u0633\u062a. \u0627\u0632 <strong>GitHub Actions<\/strong>\u060c <strong>Gemini API<\/strong> \u0648 \u06cc\u06a9 \u0627\u0633\u06a9\u0631\u06cc\u067e\u062a <strong>Python<\/strong> \u0627\u0633\u062a\u0627\u0646\u062f\u0627\u0631\u062f \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc\u200c\u0634\u0648\u062f.<\/p>\n<p><strong>\u0686\u0647\u0627\u0631 \u0645\u0631\u062d\u0644\u0647 \u0627\u0635\u0644\u06cc \u06af\u0631\u062f\u0634 \u06a9\u0627\u0631:<\/strong><br \/>\n\u06f1. <strong>\u0631\u0627\u0647\u200c\u0627\u0646\u062f\u0627\u0632:<\/strong> \u0628\u0627 \u0628\u0627\u0632\u060c \u0628\u0647\u200c\u0631\u0648\u0632\u0631\u0633\u0627\u0646\u06cc \u06cc\u0627 \u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u06cc PR \u0641\u0639\u0627\u0644 \u0645\u06cc\u200c\u0634\u0648\u062f.<br \/>\n\u06f2. <strong>\u0627\u0633\u062a\u062e\u0631\u0627\u062c Diff:<\/strong> \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u0628\u0627 <code>git diff<\/code> \u0627\u0633\u062a\u062e\u0631\u0627\u062c \u0648 \u0628\u0647 \u06f8\u06f0\u06f0 \u06a9\u06cc\u0644\u0648\u0628\u0627\u06cc\u062a \u0628\u0631\u0634 \u062f\u0627\u062f\u0647 \u0645\u06cc\u200c\u0634\u0648\u062f \u062a\u0627 \u062f\u0631 \u0645\u062d\u062f\u0648\u062f\u06cc\u062a \u062a\u0648\u06a9\u0646 \u0645\u062f\u0644 \u062c\u0627 \u0634\u0648\u062f.<br \/>\n\u06f3. <strong>\u062a\u062d\u0644\u06cc\u0644 \u0628\u0627 Gemini:<\/strong> \u06cc\u06a9 \u0627\u0633\u06a9\u0631\u06cc\u067e\u062a Python \u062e\u0637\u200c\u0647\u0627\u06cc \u062a\u063a\u06cc\u06cc\u0631 \u06cc\u0627\u0641\u062a\u0647 \u0631\u0627 \u067e\u0631\u062f\u0627\u0632\u0634 \u0645\u06cc\u200c\u06a9\u0646\u062f (\u062c\u0644\u0648\u06af\u06cc\u0631\u06cc \u0627\u0632 \u062a\u0648\u0647\u0645 \u0645\u062f\u0644 \u062f\u0631 \u0646\u0638\u0631 \u062f\u0627\u062f\u0646 \u062e\u0637\u0648\u0637 \u062b\u0627\u0628\u062a) \u0648 \u06cc\u06a9 \u067e\u0631\u0627\u0645\u067e\u062a \u0633\u0627\u062e\u062a\u0627\u0631\u06cc\u0627\u0641\u062a\u0647 \u0628\u0627 <code>response_schema<\/code>.JSON \u0628\u0647 Gemini 1.5 Flash \u0627\u0631\u0633\u0627\u0644 \u0645\u06cc\u200c\u06a9\u0646\u062f. \u0645\u062f\u0644 \u0628\u0627 \u062a\u0645\u0631\u06a9\u0632 \u0628\u0631 \u0645\u0639\u0645\u0627\u0631\u06cc\u060c \u0627\u0645\u0646\u06cc\u062a\u060c UI\/UX \u0648 \u0646\u06af\u0647\u062f\u0627\u0631\u06cc\u200c\u067e\u0630\u06cc\u0631\u06cc\u060c \u0646\u0638\u0631\u0627\u062a \u062e\u0637\u200c\u0628\u0647\u200c\u062e\u0637 \u0628\u0627 \u0634\u062f\u062a (High\/Medium\/Low) \u0628\u0631\u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.<br \/>\n\u06f4. <strong>\u062b\u0628\u062a \u0646\u0638\u0631\u0627\u062a:<\/strong> \u0627\u0633\u06a9\u0631\u06cc\u067e\u062a <code>github-script<\/code> \u062e\u0631\u0648\u062c\u06cc JSON \u0631\u0627 \u0645\u06cc\u200c\u062e\u0648\u0627\u0646\u062f \u0648 \u0646\u0638\u0631\u0627\u062a \u0631\u0627 \u0628\u0647 \u0635\u0648\u0631\u062a <strong>Inline Comments<\/strong> \u0628\u0648\u0645\u06cc GitHub \u0631\u0648\u06cc \u062e\u0637\u0648\u0637 \u062f\u0642\u06cc\u0642 \u062b\u0628\u062a \u0645\u06cc\u200c\u06a9\u0646\u062f. \u062f\u0631 \u0635\u0648\u0631\u062a \u0648\u062c\u0648\u062f \u062e\u0637\u0627\u06cc \u062c\u062f\u06cc\u060c \u0648\u0636\u0639\u06cc\u062a Review \u0628\u0647 <code>REQUEST_CHANGES<\/code> \u062a\u0646\u0638\u06cc\u0645 \u0645\u06cc\u200c\u0634\u0648\u062f.<\/p>\n<p><strong>\u0645\u0632\u0627\u06cc\u0627\u06cc \u06a9\u0644\u06cc\u062f\u06cc:<\/strong> \u06a9\u0646\u062a\u0631\u0644 \u06a9\u0627\u0645\u0644 \u0628\u0631 \u067e\u0631\u0627\u0645\u067e\u062a \u0648 \u0645\u0646\u0637\u0642\u060c \u0647\u0632\u06cc\u0646\u0647 \u067e\u0627\u06cc\u06cc\u0646 (\u0641\u0642\u0637 \u0647\u0632\u06cc\u0646\u0647 API Gemini)\u060c \u0639\u062f\u0645 \u0646\u06cc\u0627\u0632 \u0628\u0647 \u0645\u062c\u0648\u0632\u0647\u0627\u06cc \u06af\u0633\u062a\u0631\u062f\u0647 \u0645\u062e\u0632\u0646\u060c \u0648 \u0627\u0645\u06a9\u0627\u0646 \u0633\u0641\u0627\u0631\u0634\u06cc\u200c\u0633\u0627\u0632\u06cc \u0622\u0633\u0627\u0646 \u0628\u0631\u0627\u06cc \u0627\u0644\u0632\u0627\u0645\u0627\u062a \u062a\u06cc\u0645 (\u0645\u062b\u0644 \u062a\u0645\u0631\u06a9\u0632 \u0641\u0642\u0637 \u0628\u0631 \u0627\u0645\u0646\u06cc\u062a). \u06a9\u0644\u06cc\u062f API \u062f\u0631 <code>Secrets<\/code>GitHub \u0630\u062e\u06cc\u0631\u0647 \u0645\u06cc\u200c\u0634\u0648\u062f.<\/p>\n<div data-article-id=\"4157429\" id=\"article-body\">\n<p>\u0647\u0631 \u0628\u0627\u0631 \u06a9\u0647 \u0645\u0646 \u06cc\u06a9 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u0634\u0634 (PR) \u0631\u0627 \u0628\u0647 \u06cc\u06a9 \u067e\u0631\u0648\u0698\u0647 \u0645\u0646\u0628\u0639 \u0628\u0627\u0632 \u0627\u0631\u0633\u0627\u0644 \u0645\u06cc \u06a9\u0646\u0645\u060c \u0634\u0631\u0648\u0639 \u0628\u0647 \u06a9\u0627\u0631 \u062e\u0637 \u0644\u0648\u0644\u0647 CI \u0631\u0627 \u062a\u0645\u0627\u0634\u0627 \u0645\u06cc \u06a9\u0646\u0645. \u0628\u06cc\u0634\u062a\u0631 \u0648 \u0628\u06cc\u0634\u062a\u0631\u060c \u062f\u0633\u062a\u06cc\u0627\u0631 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0645\u0627\u0646\u0646\u062f CodeRabbit\u060c Copilot \u06cc\u0627 Claude \u0686\u0646\u062f \u062f\u0642\u06cc\u0642\u0647 \u0628\u0639\u062f \u0638\u0627\u0647\u0631 \u0645\u06cc \u0634\u0648\u062f \u062a\u0627 \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u0645\u0646 \u0631\u0627 \u0628\u0631\u0631\u0633\u06cc \u06a9\u0646\u062f\u060c \u0627\u0634\u06a9\u0627\u0644\u0627\u062a \u0631\u0627 \u062f\u0633\u062a\u0647 \u0628\u0646\u062f\u06cc \u06a9\u0646\u062f \u06cc\u0627 \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u0647\u0627 \u0631\u0627 \u067e\u06cc\u0634\u0646\u0647\u0627\u062f \u06a9\u0646\u062f.<\/p>\n<p>\u0645\u0646 \u0631\u0627 \u0628\u0647 \u0627\u06cc\u0646 \u0641\u06a9\u0631 \u0648\u0627\u062f\u0627\u0634\u062a: <strong>\u0633\u0627\u062e\u062a\u0646 \u06cc\u06a9\u06cc \u0627\u0632 \u0627\u06cc\u0646\u0647\u0627 \u0627\u0632 \u0627\u0628\u062a\u062f\u0627 \u0686\u0642\u062f\u0631 \u0633\u062e\u062a \u0627\u0633\u062a\u061f<\/strong><\/p>\n<p>\u0647\u0645\u0627\u0646\u0637\u0648\u0631 \u06a9\u0647 \u0645\u0634\u062e\u0635 \u0627\u0633\u062a\u060c \u0634\u0645\u0627 \u0628\u0647 \u06cc\u06a9 \u067e\u0644\u062a\u0641\u0631\u0645 \u0634\u062e\u0635 \u062b\u0627\u0644\u062b \u0633\u0646\u06af\u06cc\u0646 \u0648 \u06af\u0631\u0627\u0646 \u0642\u06cc\u0645\u062a \u0646\u06cc\u0627\u0632 \u0646\u062f\u0627\u0631\u06cc\u062f. \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u06cc\u062f \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 \u06cc\u06a9 \u0627\u0633\u06a9\u0631\u06cc\u067e\u062a \u06a9\u0648\u062a\u0627\u0647 \u067e\u0627\u06cc\u062a\u0648\u0646 \u0648 Gemini API\u060c \u06cc\u06a9 \u0645\u0631\u0648\u0631\u06af\u0631 \u06a9\u062f \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u06a9\u0627\u0645\u0644\u0627\u064b \u0633\u0641\u0627\u0631\u0634\u06cc\u200c\u0633\u0627\u0632\u06cc\u200c\u0634\u062f\u0647 \u0648 \u062e\u0637 \u0628\u0647 \u062e\u0637 \u0645\u0633\u062a\u0642\u06cc\u0645\u0627\u064b \u062f\u0631 GitHub Actions \u0628\u0633\u0627\u0632\u06cc\u062f.<\/p>\n<p>\u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u062f\u0642\u06cc\u0642\u0627\u064b \u0646\u062d\u0648\u0647 \u06a9\u0627\u0631\u060c \u0634\u06a9\u0644 \u06a9\u062f \u0648 \u0646\u062d\u0648\u0647 \u0639\u0645\u0644\u06a9\u0631\u062f \u0647\u0631 \u0642\u0637\u0639\u0647 \u062a\u0648\u0636\u06cc\u062d \u062f\u0627\u062f\u0647 \u0634\u062f\u0647 \u0627\u0633\u062a.<\/p>\n<hr\/>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_85 counter-hierarchy ez-toc-counter-rtl ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">\u0641\u0647\u0631\u0633\u062a \u0645\u0637\u0627\u0644\u0628<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"\u062a\u063a\u06cc\u06cc\u0631 \u0648\u0636\u0639\u06cc\u062a \u0641\u0647\u0631\u0633\u062a \u0645\u0637\u0627\u0644\u0628\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/nabfollower.com\/blog\/%d8%a8%d8%a7-github-actions-%db%8c%da%a9-%d8%a8%d8%a7%d8%b2%d8%a8%db%8c%d9%86%db%8c-%da%a9%d9%86%d9%86%d8%af%d9%87-ai-pr-%d8%b3%d9%81%d8%a7%d8%b1%d8%b4%db%8c-%d8%a7%d8%b2-%d8%a7%d8%a8%d8%aa%d8%af\/#%D8%A2%D9%86%DA%86%D9%87_%D9%85%D8%A7_%D8%AF%D8%B1_%D8%AD%D8%A7%D9%84_%D8%B3%D8%A7%D8%AE%D8%AA%D9%86\" >\u0622\u0646\u0686\u0647 \u0645\u0627 \u062f\u0631 \u062d\u0627\u0644 \u0633\u0627\u062e\u062a\u0646<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/nabfollower.com\/blog\/%d8%a8%d8%a7-github-actions-%db%8c%da%a9-%d8%a8%d8%a7%d8%b2%d8%a8%db%8c%d9%86%db%8c-%da%a9%d9%86%d9%86%d8%af%d9%87-ai-pr-%d8%b3%d9%81%d8%a7%d8%b1%d8%b4%db%8c-%d8%a7%d8%b2-%d8%a7%d8%a8%d8%aa%d8%af\/#%DA%A9%D8%AF_%DA%AF%D8%B1%D8%AF%D8%B4_%DA%A9%D8%A7%D8%B1_%DA%A9%D8%A7%D9%85%D9%84\" >\u06a9\u062f \u06af\u0631\u062f\u0634 \u06a9\u0627\u0631 \u06a9\u0627\u0645\u0644<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/nabfollower.com\/blog\/%d8%a8%d8%a7-github-actions-%db%8c%da%a9-%d8%a8%d8%a7%d8%b2%d8%a8%db%8c%d9%86%db%8c-%da%a9%d9%86%d9%86%d8%af%d9%87-ai-pr-%d8%b3%d9%81%d8%a7%d8%b1%d8%b4%db%8c-%d8%a7%d8%b2-%d8%a7%d8%a8%d8%aa%d8%af\/#%D8%AA%D8%AC%D8%B2%DB%8C%D9%87_%D9%82%D8%B7%D8%B9%D9%87_%D8%A8%D9%87_%D9%82%D8%B7%D8%B9%D9%87\" >\u062a\u062c\u0632\u06cc\u0647 \u0642\u0637\u0639\u0647 \u0628\u0647 \u0642\u0637\u0639\u0647<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/nabfollower.com\/blog\/%d8%a8%d8%a7-github-actions-%db%8c%da%a9-%d8%a8%d8%a7%d8%b2%d8%a8%db%8c%d9%86%db%8c-%da%a9%d9%86%d9%86%d8%af%d9%87-ai-pr-%d8%b3%d9%81%d8%a7%d8%b1%d8%b4%db%8c-%d8%a7%d8%b2-%d8%a7%d8%a8%d8%aa%d8%af\/#1_%D9%85%D8%AC%D9%88%D8%B2%D9%87%D8%A7_%D9%88_%D8%B1%D8%A7%D9%87_%D8%A7%D9%86%D8%AF%D8%A7%D8%B2%DB%8C\" >1. \u0645\u062c\u0648\u0632\u0647\u0627 \u0648 \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/nabfollower.com\/blog\/%d8%a8%d8%a7-github-actions-%db%8c%da%a9-%d8%a8%d8%a7%d8%b2%d8%a8%db%8c%d9%86%db%8c-%da%a9%d9%86%d9%86%d8%af%d9%87-ai-pr-%d8%b3%d9%81%d8%a7%d8%b1%d8%b4%db%8c-%d8%a7%d8%b2-%d8%a7%d8%a8%d8%aa%d8%af\/#2_%D8%A7%D8%B3%D8%AA%D8%AE%D8%B1%D8%A7%D8%AC_%D9%88_%D8%A8%D8%B1%D8%B4_%D8%AA%D9%81%D8%A7%D9%88%D8%AA\" >2. \u0627\u0633\u062a\u062e\u0631\u0627\u062c \u0648 \u0628\u0631\u0634 \u062a\u0641\u0627\u0648\u062a<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/nabfollower.com\/blog\/%d8%a8%d8%a7-github-actions-%db%8c%da%a9-%d8%a8%d8%a7%d8%b2%d8%a8%db%8c%d9%86%db%8c-%da%a9%d9%86%d9%86%d8%af%d9%87-ai-pr-%d8%b3%d9%81%d8%a7%d8%b1%d8%b4%db%8c-%d8%a7%d8%b2-%d8%a7%d8%a8%d8%aa%d8%af\/#3_%D8%A7%D8%B3%DA%A9%D8%B1%DB%8C%D9%BE%D8%AA_%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86_%D8%AA%D8%A3%DB%8C%DB%8C%D8%AF_%D8%AE%D8%B7%D9%88%D8%B7_%D9%88_%D9%81%D8%B1%D8%A7%D8%AE%D9%88%D8%A7%D9%86%DB%8C_%D8%AC%D9%85%DB%8C%D9%86%DB%8C\" >3. \u0627\u0633\u06a9\u0631\u06cc\u067e\u062a \u067e\u0627\u06cc\u062a\u0648\u0646 (\u062a\u0623\u06cc\u06cc\u062f \u062e\u0637\u0648\u0637 \u0648 \u0641\u0631\u0627\u062e\u0648\u0627\u0646\u06cc \u062c\u0645\u06cc\u0646\u06cc)<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/nabfollower.com\/blog\/%d8%a8%d8%a7-github-actions-%db%8c%da%a9-%d8%a8%d8%a7%d8%b2%d8%a8%db%8c%d9%86%db%8c-%da%a9%d9%86%d9%86%d8%af%d9%87-ai-pr-%d8%b3%d9%81%d8%a7%d8%b1%d8%b4%db%8c-%d8%a7%d8%b2-%d8%a7%d8%a8%d8%aa%d8%af\/#4_%D8%A7%D8%B1%D8%B3%D8%A7%D9%84_%D8%A8%D8%A7%D8%B2%D8%AE%D9%88%D8%B1%D8%AF_%D8%A8%D9%87_GitHub\" >4. \u0627\u0631\u0633\u0627\u0644 \u0628\u0627\u0632\u062e\u0648\u0631\u062f \u0628\u0647 GitHub<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/nabfollower.com\/blog\/%d8%a8%d8%a7-github-actions-%db%8c%da%a9-%d8%a8%d8%a7%d8%b2%d8%a8%db%8c%d9%86%db%8c-%da%a9%d9%86%d9%86%d8%af%d9%87-ai-pr-%d8%b3%d9%81%d8%a7%d8%b1%d8%b4%db%8c-%d8%a7%d8%b2-%d8%a7%d8%a8%d8%aa%d8%af\/#%D8%A2%D9%86_%D8%B1%D8%A7_%D8%A7%D8%B2_%D8%A2%D9%86_%D8%AE%D9%88%D8%AF_%DA%A9%D9%86%DB%8C%D8%AF\" >\u0622\u0646 \u0631\u0627 \u0627\u0632 \u0622\u0646 \u062e\u0648\u062f \u06a9\u0646\u06cc\u062f<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D8%A2%D9%86%DA%86%D9%87_%D9%85%D8%A7_%D8%AF%D8%B1_%D8%AD%D8%A7%D9%84_%D8%B3%D8%A7%D8%AE%D8%AA%D9%86\"><\/span>\n<p>  \u0622\u0646\u0686\u0647 \u0645\u0627 \u062f\u0631 \u062d\u0627\u0644 \u0633\u0627\u062e\u062a\u0646<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0647\u062f\u0641 \u0627\u06cc\u062c\u0627\u062f \u06cc\u06a9 \u062d\u0644\u0642\u0647 \u0627\u062a\u0648\u0645\u0627\u0633\u06cc\u0648\u0646 \u0633\u0628\u06a9 \u0648\u0632\u0646 \u0648 \u0628\u062f\u0648\u0646 \u0648\u0627\u0628\u0633\u062a\u06af\u06cc \u0627\u0633\u062a \u06a9\u0647 \u0645\u0627\u0646\u0646\u062f \u06cc\u06a9 \u0645\u0647\u0646\u062f\u0633 \u0627\u0631\u0634\u062f \u062f\u0631 \u062a\u06cc\u0645 \u0634\u0645\u0627 \u0639\u0645\u0644 \u0645\u06cc \u06a9\u0646\u062f.<\/p>\n<ol>\n<li>\n<p><strong>\u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u0631\u0648\u06cc\u062f\u0627\u062f\u0647\u0627\u06cc \u0631\u0648\u0627\u0628\u0637 \u0639\u0645\u0648\u0645\u06cc:<\/strong> \u0645\u0631\u062d\u0644\u0647 1.<br \/>\u0647\u0631 \u0632\u0645\u0627\u0646 \u06a9\u0647 \u06cc\u06a9 PR \u0628\u0627\u0632 \u0634\u0648\u062f\u060c \u0628\u0647 \u0631\u0648\u0632 \u0634\u0648\u062f \u06cc\u0627 \u062f\u0648\u0628\u0627\u0631\u0647 \u0628\u0627\u0632 \u0634\u0648\u062f\u060c \u06af\u0631\u062f\u0634 \u06a9\u0627\u0631 \u0622\u063a\u0627\u0632 \u0645\u06cc \u0634\u0648\u062f.<\/p>\n<\/li>\n<li>\n<p><strong>\u0627\u0633\u062a\u062e\u0631\u0627\u062c Git Diff:<\/strong> \u0645\u0631\u062d\u0644\u0647 2.<br \/>\u0645\u0627 \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u062e\u0637 \u062f\u0642\u06cc\u0642 \u0631\u0627 \u062c\u062f\u0627 \u0645\u06cc \u06a9\u0646\u06cc\u0645 \u0648 \u0622\u0646\u0647\u0627 \u0631\u0627 \u0628\u0631\u0634 \u0645\u06cc \u062f\u0647\u06cc\u0645 \u062a\u0627 \u0628\u0647 \u0631\u0627\u062d\u062a\u06cc \u062f\u0631 \u0645\u062d\u062f\u0648\u062f\u06cc\u062a \u0647\u0627\u06cc \u0632\u0645\u06cc\u0646\u0647 LLM \u0642\u0631\u0627\u0631 \u06af\u06cc\u0631\u0646\u062f.<\/p>\n<\/li>\n<li>\n<p><strong>\u0627\u0631\u0633\u0627\u0644 \u0628\u0647 Gemini \u0628\u0627 \u062e\u0631\u0648\u062c\u06cc \u0633\u0627\u062e\u062a\u0627\u0631\u06cc\u0627\u0641\u062a\u0647:<\/strong> \u0645\u0631\u062d\u0644\u0647 3.<br \/>\u06cc\u06a9 \u0627\u0633\u06a9\u0631\u06cc\u067e\u062a \u067e\u0627\u06cc\u062a\u0648\u0646 \u062f\u0631\u0648\u0646 \u062e\u0637\u06cc \u0627\u06cc\u0646 \u062a\u0641\u0627\u0648\u062a \u0631\u0627 \u0628\u0647 Gemini \u0645\u0646\u062a\u0642\u0644 \u0645\u06cc\u200c\u06a9\u0646\u062f\u060c \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 \u06cc\u06a9 \u0637\u0631\u062d \u0633\u062e\u062a\u06af\u06cc\u0631\u0627\u0646\u0647 JSON \u0628\u0631\u0627\u06cc \u062a\u0636\u0645\u06cc\u0646 \u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u0646\u0638\u0631\u0627\u062a \u0633\u0627\u062e\u062a\u0627\u0631\u0645\u0646\u062f \u0645\u0631\u062a\u0628\u0637 \u0628\u0627 \u0641\u0627\u06cc\u0644\u200c\u0647\u0627 \u0648 \u062e\u0637\u0648\u0637 \u062e\u0627\u0635.<\/p>\n<\/li>\n<li>\n<p><strong>\u0627\u0631\u0633\u0627\u0644 \u0646\u0638\u0631\u0627\u062a \u062f\u0631\u0648\u0646 \u062e\u0637\u06cc:<\/strong> \u0645\u0631\u062d\u0644\u0647 4.<br \/>\u06cc\u06a9 \u0627\u0633\u06a9\u0631\u06cc\u067e\u062a GitHub \u0628\u0627\u0631 JSON \u0631\u0627 \u0645\u06cc \u062e\u0648\u0627\u0646\u062f \u0648 \u0646\u0638\u0631\u0627\u062a \u0628\u0631\u0631\u0633\u06cc \u06a9\u062f \u0628\u0648\u0645\u06cc \u0631\u0627 \u0645\u0633\u062a\u0642\u06cc\u0645\u0627\u064b \u0628\u0647 \u062e\u0637\u0648\u0637 \u0627\u0635\u0644\u0627\u062d \u0634\u062f\u0647 \u062f\u0631 PR \u067e\u06cc\u0648\u0633\u062a \u0645\u06cc \u06a9\u0646\u062f.<\/p>\n<\/li>\n<\/ol>\n<hr\/>\n<h2><span class=\"ez-toc-section\" id=\"%DA%A9%D8%AF_%DA%AF%D8%B1%D8%AF%D8%B4_%DA%A9%D8%A7%D8%B1_%DA%A9%D8%A7%D9%85%D9%84\"><\/span>\n<p>  \u06a9\u062f \u06af\u0631\u062f\u0634 \u06a9\u0627\u0631 \u06a9\u0627\u0645\u0644<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u06cc\u06a9 \u0641\u0627\u06cc\u0644 \u0628\u0647 \u0646\u0627\u0645 \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>.github\/workflows\/ai-review.yml<\/code> \u062f\u0631 \u0645\u062e\u0632\u0646 \u062e\u0648\u062f \u0648 \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc \u0632\u06cc\u0631 \u0631\u0627 \u0642\u0631\u0627\u0631 \u062f\u0647\u06cc\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight yaml\"><code><span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">AI PR Review<\/span>\n\n<span class=\"na\">on<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">pull_request<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">types<\/span><span class=\"pi\">:<\/span> <span class=\"pi\">[<\/span><span class=\"nv\">opened<\/span><span class=\"pi\">,<\/span> <span class=\"nv\">synchronize<\/span><span class=\"pi\">,<\/span> <span class=\"nv\">reopened<\/span><span class=\"pi\">]<\/span>\n\n<span class=\"na\">permissions<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">contents<\/span><span class=\"pi\">:<\/span> <span class=\"s\">read<\/span>\n  <span class=\"na\">pull-requests<\/span><span class=\"pi\">:<\/span> <span class=\"s\">write<\/span>\n\n<span class=\"na\">jobs<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">ai-review<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">runs-on<\/span><span class=\"pi\">:<\/span> <span class=\"s\">ubuntu-latest<\/span>\n    <span class=\"na\">steps<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">uses<\/span><span class=\"pi\">:<\/span> <span class=\"s\">actions\/checkout@v4<\/span>\n        <span class=\"na\">with<\/span><span class=\"pi\">:<\/span>\n          <span class=\"na\">fetch-depth<\/span><span class=\"pi\">:<\/span> <span class=\"m\">0<\/span>\n\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Get PR diff<\/span>\n        <span class=\"na\">env<\/span><span class=\"pi\">:<\/span>\n          <span class=\"na\">BASE_SHA<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ github.event.pull_request.base.sha }}<\/span>\n          <span class=\"na\">HEAD_SHA<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ github.event.pull_request.head.sha }}<\/span>\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"pi\">|<\/span>\n          <span class=\"s\">git diff \"$BASE_SHA...$HEAD_SHA\" &gt; diff.txt<\/span>\n          <span class=\"s\">head -c 800000 diff.txt &gt; diff_trimmed.txt<\/span>\n\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Ask Gemini for a review<\/span>\n        <span class=\"na\">env<\/span><span class=\"pi\">:<\/span>\n          <span class=\"na\">GEMINI_API_KEY<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ secrets.GEMINI_API_KEY }}<\/span>\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"pi\">|<\/span>\n          <span class=\"s\">python3 - &lt;&lt;'PYEOF'<\/span>\n          <span class=\"s\">import json, os, re, sys, time<\/span>\n          <span class=\"s\">import urllib.error<\/span>\n          <span class=\"s\">import urllib.request<\/span>\n\n          <span class=\"s\">MAX_DIFF_BYTES = 800_000<\/span>\n\n          <span class=\"s\">def write_outputs(status, summary, comments):<\/span>\n              <span class=\"s\">open(\"status.txt\", \"w\").write(status)<\/span>\n              <span class=\"s\">open(\"review.md\", \"w\").write(summary)<\/span>\n              <span class=\"s\">open(\"comments.json\", \"w\").write(json.dumps(comments))<\/span>\n\n          <span class=\"s\">original_bytes = os.path.getsize(\"diff.txt\")<\/span>\n          <span class=\"s\">truncated = original_bytes &gt; MAX_DIFF_BYTES<\/span>\n\n          <span class=\"s\">with open(\"diff_trimmed.txt\", errors=\"replace\") as f:<\/span>\n              <span class=\"s\">diff = f.read()<\/span>\n\n          <span class=\"s\">if not diff.strip():<\/span>\n              <span class=\"s\">write_outputs(\"clean\", \"No changes to review.\", [])<\/span>\n              <span class=\"s\">sys.exit(0)<\/span>\n\n          <span class=\"s\">def parse_commentable_lines(diff_text):<\/span>\n              <span class=\"s\">valid = {}<\/span>\n              <span class=\"s\">current_file, new_line = None, None<\/span>\n              <span class=\"s\">for line in diff_text.splitlines():<\/span>\n                  <span class=\"s\">if line.startswith(\"+++ \"):<\/span>\n                      <span class=\"s\">raw = line[4:].strip()<\/span>\n                      <span class=\"s\">current_file = None if raw == \"\/dev\/null\" else raw[2:]  # strip \"b\/\"<\/span>\n                      <span class=\"s\">if current_file:<\/span>\n                          <span class=\"s\">valid.setdefault(current_file, set())<\/span>\n                      <span class=\"s\">new_line = None<\/span>\n                      <span class=\"s\">continue<\/span>\n                  <span class=\"s\">m = re.match(r\"^@@ -\\d+(?:,\\d+)? \\+(\\d+)(?:,\\d+)? @@\", line)<\/span>\n                  <span class=\"s\">if m:<\/span>\n                      <span class=\"s\">new_line = int(m.group(1))<\/span>\n                      <span class=\"s\">continue<\/span>\n                  <span class=\"s\">if current_file is None or new_line is None:<\/span>\n                      <span class=\"s\">continue<\/span>\n                  <span class=\"s\">if line.startswith(\"+\"):<\/span>\n                      <span class=\"s\">valid[current_file].add(new_line)  # only new\/added lines are offered<\/span>\n                      <span class=\"s\">new_line += 1<\/span>\n                  <span class=\"s\">elif line.startswith(\" \"):<\/span>\n                      <span class=\"s\">new_line += 1<\/span>\n              <span class=\"s\">return valid<\/span>\n\n          <span class=\"s\">commentable = parse_commentable_lines(diff)<\/span>\n\n          <span class=\"s\">prompt_text = \"\"\"You are a senior software engineer reviewing a pull request diff.<\/span>\n\n          <span class=\"s\">Focus strictly on:<\/span>\n          <span class=\"s\">1. Architecture &amp; Logic: bugs, security issues, missing error handling, race conditions, lifecycle conflicts.<\/span>\n          <span class=\"s\">2. UI &amp; Responsiveness<\/span>\n          <span class=\"s\">3. UX &amp; Information Density.<\/span>\n          <span class=\"s\">4. Maintainability: structural and style problems.<\/span>\n\n          <span class=\"s\">Only flag lines that are actually part of the diff (added or modified lines). Reference the NEW file's line numbers.<\/span>\n          <span class=\"s\">Zero emojis. Be brief, direct, pragmatic.<\/span>\n          <span class=\"s\">If there is nothing significant, return status \"clean\" with an empty comments array.<\/span>\n          <span class=\"s\">\"\"\" + diff<\/span>\n\n          <span class=\"s\">response_schema = {<\/span>\n              <span class=\"s\">\"type\": \"OBJECT\",<\/span>\n              <span class=\"s\">\"properties\": {<\/span>\n                  <span class=\"s\">\"status\": {\"type\": \"STRING\", \"enum\": [\"clean\", \"issues_found\"]},<\/span>\n                  <span class=\"s\">\"summary\": {\"type\": \"STRING\"},<\/span>\n                  <span class=\"s\">\"comments\": {<\/span>\n                      <span class=\"s\">\"type\": \"ARRAY\",<\/span>\n                      <span class=\"s\">\"items\": {<\/span>\n                          <span class=\"s\">\"type\": \"OBJECT\",<\/span>\n                          <span class=\"s\">\"properties\": {<\/span>\n                              <span class=\"s\">\"file\": {\"type\": \"STRING\"},<\/span>\n                              <span class=\"s\">\"line\": {\"type\": \"INTEGER\"},<\/span>\n                              <span class=\"s\">\"severity\": {\"type\": \"STRING\", \"enum\": [\"high\", \"medium\", \"low\"]},<\/span>\n                              <span class=\"s\">\"comment\": {\"type\": \"STRING\"},<\/span>\n                          <span class=\"s\">},<\/span>\n                          <span class=\"s\">\"required\": [\"file\", \"line\", \"comment\"],<\/span>\n                      <span class=\"s\">},<\/span>\n                  <span class=\"s\">},<\/span>\n              <span class=\"s\">},<\/span>\n              <span class=\"s\">\"required\": [\"status\", \"summary\", \"comments\"],<\/span>\n          <span class=\"s\">}<\/span>\n\n          <span class=\"s\">req = urllib.request.Request(<\/span>\n              <span class=\"s\">\"https:\/\/generativelanguage.googleapis.com\/v1beta\/models\/gemini-3.5-flash:generateContent\",<\/span>\n              <span class=\"s\">data=json.dumps({<\/span>\n                  <span class=\"s\">\"contents\": [{\"parts\": [{\"text\": prompt_text}]}],<\/span>\n                  <span class=\"s\">\"generationConfig\": {<\/span>\n                      <span class=\"s\">\"responseMimeType\": \"application\/json\",<\/span>\n                      <span class=\"s\">\"responseSchema\": response_schema,<\/span>\n                  <span class=\"s\">},<\/span>\n              <span class=\"s\">}).encode(),<\/span>\n              <span class=\"s\">headers={<\/span>\n                  <span class=\"s\">\"Content-Type\": \"application\/json\",<\/span>\n                  <span class=\"s\">\"x-goog-api-key\": os.environ[\"GEMINI_API_KEY\"],<\/span>\n              <span class=\"s\">},<\/span>\n          <span class=\"s\">)<\/span>\n\n          <span class=\"s\">def call_with_retries(request, max_attempts=3, base_delay=2):<\/span>\n              <span class=\"s\">last_err = None<\/span>\n              <span class=\"s\">for attempt in range(1, max_attempts + 1):<\/span>\n                  <span class=\"s\">try:<\/span>\n                      <span class=\"s\">with urllib.request.urlopen(request, timeout=180) as resp:<\/span>\n                          <span class=\"s\">return json.loads(resp.read())<\/span>\n                  <span class=\"s\">except urllib.error.HTTPError as e:<\/span>\n                      <span class=\"s\">last_err = e<\/span>\n                      <span class=\"s\">if e.code in (429, 500, 502, 503, 504) and attempt &lt; max_attempts:<\/span>\n                          <span class=\"s\">time.sleep(base_delay * attempt)<\/span>\n                          <span class=\"s\">continue<\/span>\n                      <span class=\"s\">raise<\/span>\n                  <span class=\"s\">except urllib.error.URLError as e:<\/span>\n                      <span class=\"s\">last_err = e<\/span>\n                      <span class=\"s\">if attempt &lt; max_attempts:<\/span>\n                          <span class=\"s\">time.sleep(base_delay * attempt)<\/span>\n                          <span class=\"s\">continue<\/span>\n                      <span class=\"s\">raise<\/span>\n              <span class=\"s\">raise last_err<\/span>\n\n          <span class=\"s\">try:<\/span>\n              <span class=\"s\">payload = call_with_retries(req)<\/span>\n\n              <span class=\"s\">candidates = payload.get(\"candidates\") or []<\/span>\n              <span class=\"s\">if not candidates:<\/span>\n                  <span class=\"s\">reason = payload.get(\"promptFeedback\", {}).get(\"blockReason\", \"unknown\")<\/span>\n                  <span class=\"s\">raise ValueError(f\"no candidates returned (blockReason={reason})\")<\/span>\n              <span class=\"s\">if \"content\" not in candidates[0] or \"parts\" not in candidates[0][\"content\"]:<\/span>\n                  <span class=\"s\">raise ValueError(\"response missing content\/parts\")<\/span>\n\n              <span class=\"s\">raw_text = candidates[0][\"content\"][\"parts\"][0].get(\"text\", \"\").strip()<\/span>\n              <span class=\"s\">raw_text = re.sub(r\"^```<\/span>\n<span class=\"pi\">{<\/span><span class=\"err\">%<\/span> <span class=\"nv\">endraw %<\/span><span class=\"pi\">}<\/span>\n<span class=\"s\">json\\s*|\\s*<\/span>\n<span class=\"pi\">{<\/span><span class=\"err\">%<\/span> <span class=\"nv\">raw %<\/span><span class=\"pi\">}<\/span>\n<span class=\"err\">```<\/span><span class=\"s\">$\", \"\", raw_text)<\/span>  <span class=\"c1\"># in case it wraps anyway<\/span>\n              <span class=\"s\">parsed = json.loads(raw_text)<\/span>\n\n              <span class=\"s\">status = parsed.get(\"status\", \"issues_found\")<\/span>\n              <span class=\"s\">summary = parsed.get(\"summary\", \"\").strip() or \"Review complete.\"<\/span>\n              <span class=\"s\">raw_comments = parsed.get(\"comments\", [])<\/span>\n\n              <span class=\"s\">safe_comments = []<\/span>\n              <span class=\"s\">for c in raw_comments<\/span><span class=\"err\">:<\/span>\n                  <span class=\"s\">f, ln = c.get(\"file\"), c.get(\"line\")<\/span>\n                  <span class=\"s\">if f in commentable and ln in commentable[f]<\/span><span class=\"err\">:<\/span>\n                      <span class=\"s\">severity = c.get(\"severity\", \"medium\").upper()<\/span>\n                      <span class=\"s\">safe_comments.append({<\/span>\n                          <span class=\"s\">\"path\"<\/span><span class=\"err\">:<\/span> <span class=\"s\">f,<\/span>\n                          <span class=\"s\">\"line\"<\/span><span class=\"err\">:<\/span> <span class=\"s\">ln,<\/span>\n                          <span class=\"s\">\"side\"<\/span><span class=\"err\">:<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">RIGHT\"<\/span><span class=\"err\">,<\/span>\n                          <span class=\"s2\">\"<\/span><span class=\"s\">body\"<\/span><span class=\"err\">:<\/span> <span class=\"s\">f\"**[{severity}]** {c.get('comment', '').strip()}\",<\/span>\n                      <span class=\"s\">})<\/span>\n\n              <span class=\"s\">if truncated<\/span><span class=\"err\">:<\/span>\n                  <span class=\"s\">summary = (<\/span>\n                      <span class=\"s\">f\"Note<\/span><span class=\"err\">:<\/span> <span class=\"s\">diff exceeded {MAX_DIFF_BYTES \/\/ 1000}KB and was truncated \u2014 \"<\/span>\n                      <span class=\"s\">f\"this review may not cover the full PR.\\n\\n\" + summary<\/span>\n                  <span class=\"s\">)<\/span>\n\n              <span class=\"s\">write_outputs(status, summary, safe_comments)<\/span>\n\n          <span class=\"s\">except urllib.error.HTTPError as e<\/span><span class=\"err\">:<\/span>\n              <span class=\"s\">detail = e.read().decode(errors=\"replace\")[:500]<\/span>\n              <span class=\"s\">print(f\"::warning::Gemini API HTTP {e.code}<\/span><span class=\"err\">:<\/span> <span class=\"pi\">{<\/span><span class=\"nv\">detail<\/span><span class=\"pi\">}<\/span><span class=\"s2\">\"<\/span><span class=\"s\">,<\/span><span class=\"nv\"> <\/span><span class=\"s\">file=sys.stderr)<\/span>\n              <span class=\"s\">write_outputs(\"skipped\", f\"AI review skipped<\/span><span class=\"err\">:<\/span> <span class=\"s\">Gemini API returned HTTP {e.code}.\", [])<\/span>\n\n          <span class=\"s\">except urllib.error.URLError as e<\/span><span class=\"err\">:<\/span>\n              <span class=\"s\">print(f\"::warning::Gemini API network error<\/span><span class=\"err\">:<\/span> <span class=\"pi\">{<\/span><span class=\"nv\">e<\/span><span class=\"pi\">}<\/span><span class=\"s2\">\"<\/span><span class=\"s\">,<\/span><span class=\"nv\"> <\/span><span class=\"s\">file=sys.stderr)<\/span>\n              <span class=\"s\">write_outputs(\"skipped\", f\"AI review skipped<\/span><span class=\"err\">:<\/span> <span class=\"s\">network error contacting Gemini API ({e.reason}).\", [])<\/span>\n\n          <span class=\"s\">except (KeyError, IndexError, ValueError, json.JSONDecodeError) as e<\/span><span class=\"err\">:<\/span>\n              <span class=\"s\">print(f\"::warning::Gemini API unexpected response<\/span><span class=\"err\">:<\/span> <span class=\"pi\">{<\/span><span class=\"nv\">e<\/span><span class=\"pi\">}<\/span><span class=\"s2\">\"<\/span><span class=\"s\">,<\/span><span class=\"nv\"> <\/span><span class=\"s\">file=sys.stderr)<\/span>\n              <span class=\"s\">write_outputs(\"skipped\", f\"AI review skipped<\/span><span class=\"err\">:<\/span> <span class=\"s\">unexpected response from Gemini API ({e}).\", [])<\/span>\n          <span class=\"s\">PYEOF<\/span>\n\n      <span class=\"s\">- name<\/span><span class=\"err\">:<\/span> <span class=\"s\">Submit PR Review<\/span>\n        <span class=\"s\">uses<\/span><span class=\"err\">:<\/span> <span class=\"s\">actions\/github-script@v7<\/span>\n        <span class=\"s\">with<\/span><span class=\"err\">:<\/span>\n          <span class=\"na\">script<\/span><span class=\"pi\">:<\/span> <span class=\"pi\">|<\/span>\n            <span class=\"s\">const fs = require('fs');<\/span>\n\n            <span class=\"s\">const status = fs.readFileSync('status.txt', 'utf8').trim();<\/span>\n            <span class=\"s\">const summary = fs.readFileSync('review.md', 'utf8');<\/span>\n            <span class=\"s\">let comments = [];<\/span>\n            <span class=\"s\">try {<\/span>\n              <span class=\"s\">comments = JSON.parse(fs.readFileSync('comments.json', 'utf8'));<\/span>\n            <span class=\"s\">} catch (e) {<\/span>\n              <span class=\"s\">comments = [];<\/span>\n            <span class=\"s\">}<\/span>\n\n            <span class=\"s\">const reviewEvent = (status === 'issues_found' &amp;&amp; comments.length &gt; 0)<\/span>\n              <span class=\"s\">? 'REQUEST_CHANGES'<\/span>\n              <span class=\"s\">: 'COMMENT';<\/span>\n\n            <span class=\"s\">const base = {<\/span>\n              <span class=\"s\">owner: context.repo.owner,<\/span>\n              <span class=\"s\">repo: context.repo.repo,<\/span>\n              <span class=\"s\">pull_number: context.issue.number,<\/span>\n              <span class=\"s\">event: reviewEvent,<\/span>\n            <span class=\"s\">};<\/span>\n\n            <span class=\"s\">try {<\/span>\n              <span class=\"s\">await github.rest.pulls.createReview({ ...base, body: summary, comments });<\/span>\n            <span class=\"s\">} catch (e) {<\/span>\n              <span class=\"s\">core.warning(`Inline comments rejected (${e.message}); falling back to summary only.`);<\/span>\n              <span class=\"s\">await github.rest.pulls.createReview({<\/span>\n                <span class=\"s\">...base,<\/span>\n                <span class=\"s\">body: summary + '\\n\\n_Some inline comments could not be posted._',<\/span>\n              <span class=\"s\">});<\/span>\n            <span class=\"s\">}<\/span>\n\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<hr\/>\n<h2><span class=\"ez-toc-section\" id=\"%D8%AA%D8%AC%D8%B2%DB%8C%D9%87_%D9%82%D8%B7%D8%B9%D9%87_%D8%A8%D9%87_%D9%82%D8%B7%D8%B9%D9%87\"><\/span>\n<p>  \u062a\u062c\u0632\u06cc\u0647 \u0642\u0637\u0639\u0647 \u0628\u0647 \u0642\u0637\u0639\u0647<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0628\u06cc\u0627\u06cc\u06cc\u062f \u062f\u0642\u06cc\u0642\u0627\u064b \u0646\u062d\u0648\u0647 \u0639\u0645\u0644\u06a9\u0631\u062f \u0647\u0631 \u062c\u0632\u0621 \u0631\u0627 \u0628\u0631\u0631\u0633\u06cc \u06a9\u0646\u06cc\u0645 \u062a\u0627 \u0627\u06cc\u0646 \u0627\u0645\u0631 \u0628\u0647 \u0637\u0648\u0631 \u06cc\u06a9\u067e\u0627\u0631\u0686\u0647 \u0627\u0646\u062c\u0627\u0645 \u0634\u0648\u062f.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"1_%D9%85%D8%AC%D9%88%D8%B2%D9%87%D8%A7_%D9%88_%D8%B1%D8%A7%D9%87_%D8%A7%D9%86%D8%AF%D8%A7%D8%B2%DB%8C\"><\/span>\n<p>  1. \u0645\u062c\u0648\u0632\u0647\u0627 \u0648 \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u062f\u0631 \u0628\u0627\u0644\u0627\u06cc \u06af\u0631\u062f\u0634 \u06a9\u0627\u0631\u060c \u0631\u0627\u0647\u200c\u0627\u0646\u062f\u0627\u0632\u0647\u0627 \u0648 \u0645\u062c\u0648\u0632\u0647\u0627\u06cc \u0631\u0648\u06cc\u062f\u0627\u062f \u0631\u0627 \u062a\u0639\u0631\u06cc\u0641 \u0645\u06cc\u200c\u06a9\u0646\u06cc\u0645:<\/p>\n<ul>\n<li>\n<code>pull_request<\/code>  \u0627\u0646\u0648\u0627\u0639 \u0627\u0637\u0645\u06cc\u0646\u0627\u0646 \u062d\u0627\u0635\u0644 \u0645\u06cc \u06a9\u0646\u0646\u062f \u06a9\u0647 \u0648\u0642\u062a\u06cc \u06a9\u062f \u062a\u063a\u06cc\u06cc\u0631 \u0645\u06cc \u06a9\u0646\u062f \u06cc\u0627 \u06cc\u06a9 PR \u062c\u062f\u06cc\u062f \u0641\u0639\u0627\u0644 \u0645\u06cc \u0634\u0648\u062f\u060c \u0627\u062c\u0631\u0627 \u0645\u06cc \u0634\u0648\u062f.<\/li>\n<li>\u0645\u0627 \u0628\u0647 \u0635\u0631\u0627\u062d\u062a \u06a9\u0627\u0631 \u0631\u0627 \u0645\u06cc \u062f\u0647\u06cc\u0645 <code>pull-requests: write<\/code> \u0645\u062c\u0648\u0632\u0647\u0627 \u0628\u062f\u0648\u0646 \u0627\u06cc\u0646\u060c \u062f\u0648\u0646\u062f\u0647 \u0627\u062c\u0627\u0632\u0647 \u0646\u062e\u0648\u0627\u0647\u062f \u062f\u0627\u0634\u062a \u062f\u0631 \u0645\u0648\u0636\u0648\u0639 \u0631\u0648\u0627\u0628\u0637 \u0639\u0645\u0648\u0645\u06cc \u0646\u0638\u0631 \u0628\u06af\u0630\u0627\u0631\u062f.<\/li>\n<li>\n<code>fetch-depth: 0<\/code>  \u0627\u0637\u0645\u06cc\u0646\u0627\u0646 \u062d\u0627\u0635\u0644 \u0645\u06cc \u06a9\u0646\u062f \u06a9\u0647 \u062a\u0627\u0631\u06cc\u062e\u0686\u0647 git \u06a9\u0627\u0645\u0644 \u067e\u0627\u06cc\u06cc\u0646 \u06a9\u0634\u06cc\u062f\u0647 \u0634\u062f\u0647 \u0627\u0633\u062a \u062a\u0627 \u0628\u062a\u0648\u0627\u0646\u06cc\u0645 \u0634\u0627\u062e\u0647 \u0647\u0627 \u0631\u0627 \u0628\u0647 \u0637\u0648\u0631 \u062f\u0642\u06cc\u0642 \u0645\u0642\u0627\u06cc\u0633\u0647 \u06a9\u0646\u06cc\u0645.<\/li>\n<\/ul>\n<h3><span class=\"ez-toc-section\" id=\"2_%D8%A7%D8%B3%D8%AA%D8%AE%D8%B1%D8%A7%D8%AC_%D9%88_%D8%A8%D8%B1%D8%B4_%D8%AA%D9%81%D8%A7%D9%88%D8%AA\"><\/span>\n<p>  2. \u0627\u0633\u062a\u062e\u0631\u0627\u062c \u0648 \u0628\u0631\u0634 \u062a\u0641\u0627\u0648\u062a<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight yaml\"><code><span class=\"s\">git diff \"$BASE_SHA...$HEAD_SHA\" &gt; diff.txt<\/span>\n<span class=\"s\">head -c 800000 diff.txt &gt; diff_trimmed.txt<\/span>\n\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0628\u0647\u200c\u062c\u0627\u06cc \u062a\u06a9\u06cc\u0647 \u0628\u0631 \u0648\u0627\u0628\u0633\u062a\u06af\u06cc\u200c\u0647\u0627\u06cc \u0634\u062f\u06cc\u062f \u0627\u06a9\u0648\u0633\u06cc\u0633\u062a\u0645\u060c \u0645\u062a\u0646 \u0627\u0633\u062a\u0627\u0646\u062f\u0627\u0631\u062f git diff \u0631\u0627 \u0645\u06cc\u200c\u06a9\u0634\u06cc\u0645. \u062f\u0631\u062e\u0648\u0627\u0633\u062a\u200c\u0647\u0627\u06cc \u06a9\u0634\u0634 \u0639\u0638\u06cc\u0645 \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u0646\u062f \u0628\u0647 \u0633\u0631\u0639\u062a \u0627\u0632 \u0645\u062d\u062f\u0648\u062f\u06cc\u062a\u200c\u0647\u0627\u06cc \u0628\u0632\u0631\u06af \u0645\u062f\u0644 \u0632\u0628\u0627\u0646 \u06cc\u0627 \u0645\u062d\u062f\u0648\u062f\u06cc\u062a\u200c\u0647\u0627\u06cc API \u0641\u0631\u0627\u062a\u0631 \u0628\u0631\u0648\u0646\u062f\u060c \u0628\u0646\u0627\u0628\u0631\u0627\u06cc\u0646 <code>head -c 800000<\/code> \u0628\u0631\u0627\u06cc \u062c\u0644\u0648\u06af\u06cc\u0631\u06cc \u0627\u0632 \u0627\u0641\u062a \u0633\u0627\u062e\u062a\u0627\u0631\u06cc\u060c \u062d\u062c\u0645 \u0645\u062d\u0645\u0648\u0644\u0647 \u0631\u0627 \u0628\u0627 \u062e\u06cc\u0627\u0644 \u0631\u0627\u062d\u062a \u062f\u0631 \u062d\u062f\u0648\u062f 800 \u06a9\u06cc\u0644\u0648\u0628\u0627\u06cc\u062a \u0642\u0631\u0627\u0631 \u062f\u0647\u06cc\u062f.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"3_%D8%A7%D8%B3%DA%A9%D8%B1%DB%8C%D9%BE%D8%AA_%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86_%D8%AA%D8%A3%DB%8C%DB%8C%D8%AF_%D8%AE%D8%B7%D9%88%D8%B7_%D9%88_%D9%81%D8%B1%D8%A7%D8%AE%D9%88%D8%A7%D9%86%DB%8C_%D8%AC%D9%85%DB%8C%D9%86%DB%8C\"><\/span>\n<p>  3. \u0627\u0633\u06a9\u0631\u06cc\u067e\u062a \u067e\u0627\u06cc\u062a\u0648\u0646 (\u062a\u0623\u06cc\u06cc\u062f \u062e\u0637\u0648\u0637 \u0648 \u0641\u0631\u0627\u062e\u0648\u0627\u0646\u06cc \u062c\u0645\u06cc\u0646\u06cc)<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0645\u0646\u0637\u0642 \u0627\u0635\u0644\u06cc \u062f\u0631 \u06cc\u06a9 \u0645\u0631\u062d\u0644\u0647 \u067e\u0627\u06cc\u062a\u0648\u0646 \u0628\u062f\u0648\u0646 \u0648\u0627\u0628\u0633\u062a\u06af\u06cc \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 \u06a9\u062a\u0627\u0628\u062e\u0627\u0646\u0647 \u0647\u0627\u06cc \u0627\u0633\u062a\u0627\u0646\u062f\u0627\u0631\u062f \u0627\u062c\u0631\u0627 \u0645\u06cc \u0634\u0648\u062f (<code>urllib<\/code>). \u0633\u0647 \u0645\u0634\u06a9\u0644 \u0627\u0635\u0644\u06cc \u0631\u0627 \u062d\u0644 \u0645\u06cc \u06a9\u0646\u062f:<\/p>\n<ul>\n<li>\n<strong>\u062a\u0637\u0628\u06cc\u0642 \u0647\u062f\u0641 \u062e\u0637 (<code>parse_commentable_lines<\/code>):<\/strong> LLM \u0647\u0627 \u06af\u0627\u0647\u06cc \u0627\u0648\u0642\u0627\u062a \u062f\u0686\u0627\u0631 \u062a\u0648\u0647\u0645 \u0645\u06cc \u0634\u0648\u0646\u062f \u0648 \u0633\u0639\u06cc \u0645\u06cc \u06a9\u0646\u0646\u062f \u062f\u0631 \u0645\u0648\u0631\u062f \u062e\u0637\u0648\u0637\u06cc \u06a9\u0647 \u062d\u062a\u06cc \u062a\u063a\u06cc\u06cc\u0631 \u0646\u06a9\u0631\u062f\u0647 \u0627\u0646\u062f \u0627\u0638\u0647\u0627\u0631 \u0646\u0638\u0631 \u06a9\u0646\u0646\u062f. \u0627\u06cc\u0646 \u062a\u0627\u0628\u0639 \u0647\u062f\u0631\u0647\u0627\u06cc \u06cc\u06a9\u067e\u0627\u0631\u0686\u0647 \u062a\u0641\u0627\u0648\u062a (<code>@@ -line,v +line,v @@<\/code>) \u0628\u0631\u0627\u06cc \u0633\u0627\u062e\u062a\u0646 \u0646\u0642\u0634\u0647 \u0627\u06cc \u0627\u0632 \u062e\u0637\u0648\u0637\u06cc \u06a9\u0647 \u062f\u0631 \u0648\u0627\u0642\u0639 \u0648\u062c\u0648\u062f \u062f\u0627\u0631\u0646\u062f <em>\u062c\u062f\u06cc\u062f<\/em> \u0646\u0633\u062e\u0647 \u06a9\u062f \u0648\u0631\u0648\u062f\u06cc<\/li>\n<li>\n<strong>\u0642\u0648\u0627\u0646\u06cc\u0646 \u0632\u0645\u06cc\u0646\u0647 \u062a\u0632\u0631\u06cc\u0642\u06cc:<\/strong> \u0627\u06cc\u0646 <code>prompt_text<\/code> \u0646\u0631\u062f\u0647 \u0647\u0627\u06cc \u0633\u0627\u0632\u0647 \u0627\u06cc \u0631\u0627 \u0641\u0631\u0627\u0647\u0645 \u0645\u06cc \u06a9\u0646\u062f. \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u06cc\u062f \u0627\u06cc\u0646 \u0645\u0648\u0631\u062f \u0631\u0627 \u0628\u0631\u0627\u06cc \u0645\u0637\u0627\u0628\u0642\u062a \u0628\u0627 \u0627\u0644\u0632\u0627\u0645\u0627\u062a \u0641\u0646\u06cc \u067e\u0634\u062a\u0647 \u062e\u0627\u0635 \u062e\u0648\u062f (\u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0645\u062b\u0627\u0644\u060c \u0645\u0634\u0627\u0648\u0631\u0647 \u062f\u0631 \u0645\u0648\u0631\u062f \u0686\u0631\u062e\u0647\u200c\u0647\u0627\u06cc \u0639\u0645\u0631 \u0631\u0627\u0628\u0637 \u06a9\u0627\u0631\u0628\u0631\u06cc\u060c \u0686\u0627\u0631\u0686\u0648\u0628\u200c\u0647\u0627\u06cc CSS \u06cc\u0627 \u0627\u0648\u0644\u0648\u06cc\u062a\u200c\u0647\u0627\u06cc \u0633\u0627\u062e\u062a\u0627\u0631\u06cc) \u062a\u0637\u0628\u06cc\u0642 \u062f\u0647\u06cc\u062f.<\/li>\n<li>\n<strong>\u0627\u062c\u0631\u0627\u06cc JSON \u0633\u0627\u062e\u062a\u0627\u0631\u06cc\u0627\u0641\u062a\u0647:<\/strong> \u0627\u0644\u0641 \u0631\u0627 \u062a\u0639\u0631\u06cc\u0641 \u0645\u06cc \u06a9\u0646\u06cc\u0645 <code>response_schema<\/code> \u0645\u0633\u062a\u0642\u06cc\u0645\u0627\u064b \u062f\u0631 \u062f\u0627\u062e\u0644 \u06af\u0632\u06cc\u0646\u0647 \u0647\u0627\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a API. \u0627\u06cc\u0646 \u0631\u0627 \u0645\u062c\u0628\u0648\u0631 \u0645\u06cc \u06a9\u0646\u062f <code>AI model<\/code> \u0628\u0631\u0627\u06cc \u0628\u0631\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u062f\u0627\u062f\u0647 \u0647\u0627\u06cc \u062e\u0627\u0645 \u062f\u0642\u06cc\u0642\u0627\u064b \u0645\u0637\u0627\u0628\u0642 \u0628\u0627 \u06cc\u06a9 \u0634\u06cc \u062d\u0627\u0648\u06cc \u06cc\u06a9 \u0631\u0634\u062a\u0647 \u0648\u0636\u0639\u06cc\u062a\u060c \u062e\u0644\u0627\u0635\u0647 \u0639\u0644\u0627\u0645\u062a \u06af\u0630\u0627\u0631\u06cc\u060c \u0648 \u0622\u0631\u0627\u06cc\u0647 \u0627\u06cc \u0627\u0632 \u0646\u0638\u0631\u0627\u062a \u062f\u0631\u0648\u0646 \u062e\u0637\u06cc.<\/li>\n<\/ul>\n<p>\u0627\u0633\u06a9\u0631\u06cc\u067e\u062a \u0628\u0627 \u062a\u0623\u06cc\u06cc\u062f \u0627\u06cc\u0646\u06a9\u0647 \u0628\u0627\u0632\u062e\u0648\u0631\u062f \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u062f\u0642\u06cc\u0642\u0627\u064b \u0628\u0627 \u062e\u0637\u0648\u0637 \u062a\u063a\u06cc\u06cc\u0631 \u06cc\u0627\u0641\u062a\u0647 \u0645\u0637\u0627\u0628\u0642\u062a \u062f\u0627\u0631\u062f \u067e\u0627\u06cc\u0627\u0646 \u0645\u06cc \u06cc\u0627\u0628\u062f \u0648 \u0628\u0627\u0631 \u062e\u0631\u0648\u062c\u06cc \u0631\u0627 \u062f\u0631 \u0641\u0627\u06cc\u0644 \u0647\u0627\u06cc \u0645\u062a\u0646\u06cc \u0645\u062d\u0644\u06cc \u0645\u06cc \u0646\u0648\u06cc\u0633\u062f.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"4_%D8%A7%D8%B1%D8%B3%D8%A7%D9%84_%D8%A8%D8%A7%D8%B2%D8%AE%D9%88%D8%B1%D8%AF_%D8%A8%D9%87_GitHub\"><\/span>\n<p>  4. \u0627\u0631\u0633\u0627\u0644 \u0628\u0627\u0632\u062e\u0648\u0631\u062f \u0628\u0647 GitHub<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight javascript\"><code><span class=\"kd\">const<\/span> <span class=\"nx\">reviewEvent<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">status<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">issues_found<\/span><span class=\"dl\">'<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">comments<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"p\">)<\/span> <span class=\"p\">?<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">REQUEST_CHANGES<\/span><span class=\"dl\">'<\/span> <span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">COMMENT<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">...<\/span>\n<span class=\"k\">await<\/span> <span class=\"nx\">github<\/span><span class=\"p\">.<\/span><span class=\"nx\">rest<\/span><span class=\"p\">.<\/span><span class=\"nx\">pulls<\/span><span class=\"p\">.<\/span><span class=\"nf\">createReview<\/span><span class=\"p\">({<\/span> <span class=\"p\">...<\/span><span class=\"nx\">base<\/span><span class=\"p\">,<\/span> <span class=\"na\">body<\/span><span class=\"p\">:<\/span> <span class=\"nx\">summary<\/span><span class=\"p\">,<\/span> <span class=\"nx\">comments<\/span> <span class=\"p\">});<\/span>\n\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0645\u0631\u062d\u0644\u0647 \u0646\u0647\u0627\u06cc\u06cc \u0627\u0632 \u0631\u0633\u0645\u06cc \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u062f <code>actions\/github-script<\/code> \u0627\u0642\u062f\u0627\u0645 \u0628\u0631\u0627\u06cc \u067e\u0631\u062f\u0627\u0632\u0634 \u0622\u0646 \u0641\u0627\u06cc\u0644 \u0647\u0627\u06cc \u0645\u062a\u0646\u06cc. \u0627\u06af\u0631 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u062e\u0637\u0627\u0647\u0627\u06cc \u0645\u0646\u0637\u0642\u06cc \u0648\u0627\u0642\u0639\u06cc \u0631\u0627 \u0639\u0644\u0627\u0645\u062a \u06af\u0630\u0627\u0631\u06cc \u06a9\u0646\u062f \u0648 \u0646\u0638\u0631\u0627\u062a \u0645\u0639\u062a\u0628\u0631 \u0631\u0627 \u067e\u0631 \u06a9\u0646\u062f\u060c \u0627\u0633\u06a9\u0631\u06cc\u067e\u062a \u0648\u0636\u0639\u06cc\u062a \u0628\u0631\u0631\u0633\u06cc \u0631\u0648\u0627\u0628\u0637 \u0639\u0645\u0648\u0645\u06cc \u0631\u0627 \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0639\u0644\u0627\u0645\u062a \u06af\u0630\u0627\u0631\u06cc \u0645\u06cc \u06a9\u0646\u062f. <code>REQUEST_CHANGES<\/code>. \u0627\u06af\u0631 \u0647\u0645\u0647 \u0686\u06cc\u0632 \u0648\u0627\u0636\u062d \u0628\u0647 \u0646\u0638\u0631 \u0645\u06cc \u0631\u0633\u062f\u060c \u0628\u0647 \u0637\u0648\u0631 \u067e\u06cc\u0634 \u0641\u0631\u0636 \u06cc\u06a9 \u0631\u062f\u06cc\u0627\u0628\u06cc \u0627\u0633\u062a\u0627\u0646\u062f\u0627\u0631\u062f \u0627\u0633\u062a <code>COMMENT<\/code>.<\/p>\n<p>\u0627\u06af\u0631 \u0646\u0627\u0647\u0645\u0627\u0647\u0646\u06af\u06cc \u0634\u0627\u062e\u0635 \u062e\u0637 \u062e\u0627\u0635\u06cc \u0631\u062e \u062f\u0647\u062f\u060c \u06cc\u06a9 \u0628\u0644\u0648\u06a9 try\/catch \u0628\u0647\u200c\u0639\u0646\u0648\u0627\u0646 \u06cc\u06a9 \u0628\u06a9 \u06af\u0631\u0627\u0646\u062f \u0628\u0631\u0627\u06cc \u0627\u0631\u0633\u0627\u0644 \u0628\u0631\u0631\u0633\u06cc \u062e\u0644\u0627\u0635\u0647 \u0633\u0637\u062d \u0628\u0627\u0644\u0627 \u0627\u0635\u0644\u06cc \u0639\u0645\u0644 \u0645\u06cc\u200c\u06a9\u0646\u062f \u062a\u0627 \u0628\u06cc\u0646\u0634 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0631\u0627 \u0627\u0632 \u062f\u0633\u062a \u0646\u062f\u0647\u06cc\u062f.<\/p>\n<hr\/>\n<h2><span class=\"ez-toc-section\" id=\"%D8%A2%D9%86_%D8%B1%D8%A7_%D8%A7%D8%B2_%D8%A2%D9%86_%D8%AE%D9%88%D8%AF_%DA%A9%D9%86%DB%8C%D8%AF\"><\/span>\n<p>  \u0622\u0646 \u0631\u0627 \u0627\u0632 \u0622\u0646 \u062e\u0648\u062f \u06a9\u0646\u06cc\u062f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0632\u06cc\u0628\u0627\u06cc\u06cc \u0627\u06cc\u0646 \u062a\u0646\u0638\u06cc\u0645\u0627\u062a \u0627\u06cc\u0646 \u0627\u0633\u062a \u06a9\u0647 \u062a\u063a\u06cc\u06cc\u0631 \u0622\u0646 \u0622\u0633\u0627\u0646 \u0627\u0633\u062a. \u0628\u0627 \u062a\u0646\u0638\u06cc\u0645 <code>prompt_text<\/code> \u062f\u0631 \u0628\u062e\u0634 \u0628\u0644\u0648\u06a9 \u067e\u0627\u06cc\u062a\u0648\u0646\u060c \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u06cc\u062f \u0628\u0647 \u0631\u0627\u062d\u062a\u06cc \u0628\u0647 LLM \u062f\u0633\u062a\u0648\u0631 \u062f\u0647\u06cc\u062f \u06a9\u0647 \u0628\u0647 \u06cc\u06a9 \u0632\u0628\u0627\u0646 \u062e\u0627\u0635 \u0628\u0646\u0648\u06cc\u0633\u062f\u060c \u0628\u0647 \u0634\u062f\u062a \u0631\u0648\u06cc \u0622\u0633\u06cc\u0628\u200c\u067e\u0630\u06cc\u0631\u06cc\u200c\u0647\u0627\u06cc \u0627\u0645\u0646\u06cc\u062a\u06cc \u062a\u0645\u0631\u06a9\u0632 \u06a9\u0646\u062f\u060c \u06cc\u0627 \u0647\u0645\u0647 \u0686\u06cc\u0632 \u0631\u0627 \u0628\u0647 \u062c\u0632 \u0645\u0639\u06cc\u0627\u0631\u0647\u0627\u06cc \u0639\u0645\u0644\u06a9\u0631\u062f \u062e\u0648\u062f \u0646\u0627\u062f\u06cc\u062f\u0647 \u0628\u06af\u06cc\u0631\u062f. \u0631\u0647\u0627 \u06a9\u0646\u06cc\u062f <code>GEMINI_API_KEY<\/code> \u0628\u0647 \u0627\u0633\u0631\u0627\u0631 \u0645\u062e\u0632\u0646 GitHub \u062e\u0648\u062f \u0628\u0631\u0648\u06cc\u062f\u060c \u0648 \u0634\u0645\u0627 \u06cc\u06a9 \u062d\u0641\u0627\u0638 \u06a9\u062f \u062e\u0648\u062f\u06a9\u0627\u0631 \u0648 \u062e\u0648\u062f \u0645\u06cc\u0632\u0628\u0627\u0646 \u062f\u0627\u0631\u06cc\u062f \u06a9\u0647 \u06a9\u0627\u0645\u0644\u0627\u064b \u062a\u062d\u062a \u06a9\u0646\u062a\u0631\u0644 \u0634\u0645\u0627 \u0627\u0633\u062a!<\/p>\n<p>\u0644\u06cc\u0646\u06a9 Github<\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u0633\u0627\u062e\u062a \u0645\u0631\u0648\u0631\u06af\u0631 \u06a9\u062f \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0633\u0641\u0627\u0631\u0634\u06cc \u0628\u0627 Gemini \u062f\u0631 GitHub Actions \u0627\u06cc\u0646 \u0645\u0642\u0627\u0644\u0647 \u0631\u0627\u0647\u0646\u0645\u0627\u06cc \u0633\u0627\u062e\u062a \u06cc\u06a9 \u0631\u0628\u0627\u062a \u0645\u0631\u0648\u0631\u06af\u0631 \u06a9\u062f (Code Reviewer) \u062e\u0648\u062f\u06a9\u0627\u0631\u060c \u0633\u0628\u06a9\u200c\u0648\u0632\u0646 \u0648 \u0628\u062f\u0648\u0646 \u0648\u0627\u0628\u0633\u062a\u06af\u06cc \u0628\u0647 \u0633\u0631\u0648\u06cc\u0633\u200c\u0647\u0627\u06cc \u0634\u062e\u0635 \u062b\u0627\u0644\u062b (\u0645\u0627\u0646\u0646\u062f CodeRabbit \u06cc\u0627 Copilot) \u0627\u0633\u062a. \u0627\u0632 GitHub Actions\u060c Gemini API \u0648 \u06cc\u06a9 \u0627\u0633\u06a9\u0631\u06cc\u067e\u062a Python \u0627\u0633\u062a\u0627\u0646\u062f\u0627\u0631\u062f \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc\u200c\u0634\u0648\u062f. \u0686\u0647\u0627\u0631 \u0645\u0631\u062d\u0644\u0647 \u0627\u0635\u0644\u06cc \u06af\u0631\u062f\u0634 \u06a9\u0627\u0631: \u06f1. \u0631\u0627\u0647\u200c\u0627\u0646\u062f\u0627\u0632: \u0628\u0627 &hellip;<\/p>\n","protected":false},"author":2,"featured_media":112532,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/media2.dev.to\/dynamic\/image\/width=1200,height=627,fit=cover,gravity=auto,format=auto\/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3onjra031i1gdd6l584x.png","fifu_image_alt":"","footnotes":""},"categories":[339],"tags":[],"class_list":["post-112531","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dev"],"_links":{"self":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts\/112531","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/comments?post=112531"}],"version-history":[{"count":0,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts\/112531\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/media\/112532"}],"wp:attachment":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/media?parent=112531"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/categories?post=112531"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/tags?post=112531"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}