From ab69c30f106d5b068e90cb67120dc3d22e685d00 Mon Sep 17 00:00:00 2001 From: rsb-23 <57601627+rsb-23@users.noreply.github.com> Date: Sun, 1 Dec 2024 19:58:56 +0530 Subject: [PATCH 01/13] Added PAT to workflow PR comment token fix - a typo to test --- .github/workflows/test.yml | 1 + action.yml | 5 +++++ tests/file.json | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c4d2ab6..0f9370a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,6 +15,7 @@ jobs: id: spelling uses: ./ with: + token: ${{ secrets.PAT }} files: | tests/file.txt tests/file.json diff --git a/action.yml b/action.yml index 7fd5e1f..e312057 100644 --- a/action.yml +++ b/action.yml @@ -13,6 +13,10 @@ inputs: GROQ_API_KEY: description: 'Groq API Key' required: true + token: + description: 'PAT with pull_request:write permission' + required: true + default: ${{ github.token }} outputs: comment: @@ -48,5 +52,6 @@ runs: - name: Comment PR uses: peter-evans/create-or-update-comment@v4 with: + token: ${{ inputs.token }} issue-number: ${{ github.event.pull_request.number }} body: ${{ steps.spelling.outputs.comment }} diff --git a/tests/file.json b/tests/file.json index a67a9c7..237b021 100644 --- a/tests/file.json +++ b/tests/file.json @@ -1 +1 @@ -{"fruit1": "pineaple", "friut2": "gauva"} +{"fruit1": "pineaple", "friut2": "graep"} From 5dfa2093000ce22eea80aebb2cc13e0237a0bd81 Mon Sep 17 00:00:00 2001 From: rsb-23 <57601627+rsb-23@users.noreply.github.com> Date: Sun, 1 Dec 2024 20:10:42 +0530 Subject: [PATCH 02/13] Fixed comment format --- src/spell_check.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/spell_check.py b/src/spell_check.py index 7725960..bbc2350 100644 --- a/src/spell_check.py +++ b/src/spell_check.py @@ -1,4 +1,3 @@ -import json import os import subprocess @@ -29,12 +28,12 @@ def main(): # Create markdown comment for fixes flag = False - comment = "## Suggested Typo Fixes\n\n" + comment = "### Suggested Typo Fixes\n" for file_path, suggestion in results.items(): if suggestion == -1: continue suggestion = "\n ".join(suggestion) - comment += f"- {file_path}:\n {suggestion}\n" + comment += f"\n- {file_path}:\n {suggestion}" flag = True if flag: comment += "\n**Tip**: Create a commit in this PR itself." @@ -43,7 +42,7 @@ def main(): # Set output for GitHub Actions with open(os.environ["GITHUB_OUTPUT"], "a") as f: - f.write(f"comment={json.dumps(comment)}\n") + f.write(f"comment={comment}\n") print(comment) From 030420524db0fb8922b839f37181c69588f1be50 Mon Sep 17 00:00:00 2001 From: rsb-23 <57601627+rsb-23@users.noreply.github.com> Date: Sun, 1 Dec 2024 20:35:58 +0530 Subject: [PATCH 03/13] some syntax error --- src/spell_check.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/spell_check.py b/src/spell_check.py index bbc2350..8f0441c 100644 --- a/src/spell_check.py +++ b/src/spell_check.py @@ -33,10 +33,10 @@ def main(): if suggestion == -1: continue suggestion = "\n ".join(suggestion) - comment += f"\n- {file_path}:\n {suggestion}" + comment += f"- {file_path}:\n {suggestion}\n" flag = True if flag: - comment += "\n**Tip**: Create a commit in this PR itself." + comment += "**Tip**: Create a commit in this PR itself." else: comment = "### No typos found" From 26b349dfe5740bc9c760c3f34e61d550e2d7c78d Mon Sep 17 00:00:00 2001 From: rsb-23 <57601627+rsb-23@users.noreply.github.com> Date: Sun, 1 Dec 2024 20:40:59 +0530 Subject: [PATCH 04/13] syntax fix --- src/spell_check.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spell_check.py b/src/spell_check.py index 8f0441c..09cb851 100644 --- a/src/spell_check.py +++ b/src/spell_check.py @@ -42,7 +42,7 @@ def main(): # Set output for GitHub Actions with open(os.environ["GITHUB_OUTPUT"], "a") as f: - f.write(f"comment={comment}\n") + f.write(f"comment={comment.encode()}\n") print(comment) From acfb8054c515630b0019781cd4f47e7e02999ff0 Mon Sep 17 00:00:00 2001 From: rsb-23 <57601627+rsb-23@users.noreply.github.com> Date: Mon, 2 Dec 2024 01:37:18 +0530 Subject: [PATCH 05/13] Using PR comment api --- action.yml | 10 +++------- local_test.py | 12 +++--------- requirements.txt | 1 + src/groq_ai.py | 3 ++- src/spell_check.py | 23 ++++++++++++++++++----- 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/action.yml b/action.yml index e312057..b0e293a 100644 --- a/action.yml +++ b/action.yml @@ -47,11 +47,7 @@ runs: PR_BASE: ${{ github.event.pull_request.base.ref }} INPUT_FILES: ${{ inputs.files }} GROQ_API_KEY: ${{ inputs.GROQ_API_KEY }} - run: python src/spell_check.py - - - name: Comment PR - uses: peter-evans/create-or-update-comment@v4 - with: token: ${{ inputs.token }} - issue-number: ${{ github.event.pull_request.number }} - body: ${{ steps.spelling.outputs.comment }} + PR_NO: ${{ github.event.pull_request.number }} + repo: $GITHUB_REPOSITORY + run: python src/spell_check.py diff --git a/local_test.py b/local_test.py index b4b1d73..291c8a7 100644 --- a/local_test.py +++ b/local_test.py @@ -1,17 +1,11 @@ -import os -import tempfile - from src.spell_check import main def run(): - if "GITHUB_OUTPUT" not in os.environ: - from dotenv import load_dotenv + from dotenv import load_dotenv - load_dotenv() - with tempfile.NamedTemporaryFile(mode="w+", delete_on_close=False) as f: - os.environ["GITHUB_OUTPUT"] = f.name - main() + load_dotenv() + main() if __name__ == "__main__": diff --git a/requirements.txt b/requirements.txt index 277e504..728655f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ groq==0.13.0 +requests~=2.32.3 diff --git a/src/groq_ai.py b/src/groq_ai.py index 3f70555..f337809 100644 --- a/src/groq_ai.py +++ b/src/groq_ai.py @@ -34,7 +34,8 @@ def ask_groq(query_text: str, system_content: str, json_schema: dict = None) -> return json.loads(json_str.replace("\n", "")) except json.JSONDecodeError as e: print(e.doc, e.pos) - raise + print(f"ERROR : {e.args}") + return {"suggestions": "..."} def find_typos(query_text): diff --git a/src/spell_check.py b/src/spell_check.py index 09cb851..833bcef 100644 --- a/src/spell_check.py +++ b/src/spell_check.py @@ -1,6 +1,8 @@ import os import subprocess +import requests + from groq_ai import find_typos @@ -11,13 +13,26 @@ def process_diff(file_path, base_branch): diff_output = subprocess.check_output(diff_command.split()).decode("utf-8") except subprocess.CalledProcessError: print("Error in process diff") - return 0 + return -1 # only checks for typos in added text new_text = "".join(x for x in diff_output.splitlines(keepends=True) if x.startswith("+")) return find_typos(new_text) if new_text else -1 +def post_comment(comment): + pr_no = os.environ["PR_NO"] + repo = os.environ["repo"] + url = f"https://api.github.com/repos/{repo}/issues/{pr_no}/comments" + headers = { + "Accept": "application/vnd.github+json", + "Authorization": f"Bearer {os.environ['token']}", + "X-GitHub-Api-Version": "2022-11-28", + } + resp = requests.post(url, headers=headers, json={"body": comment}) + resp.raise_for_status() + + def main(): # Get required inputs pr_base = os.environ["PR_BASE"] @@ -36,14 +51,12 @@ def main(): comment += f"- {file_path}:\n {suggestion}\n" flag = True if flag: - comment += "**Tip**: Create a commit in this PR itself." + comment += "\n**Tip**: Create a commit in this PR itself." else: comment = "### No typos found" - # Set output for GitHub Actions - with open(os.environ["GITHUB_OUTPUT"], "a") as f: - f.write(f"comment={comment.encode()}\n") print(comment) + post_comment(comment) if __name__ == "__main__": From 97c54807d9f1ad54c426e3f65ce27f0042e1a234 Mon Sep 17 00:00:00 2001 From: rsb-23 <57601627+rsb-23@users.noreply.github.com> Date: Mon, 2 Dec 2024 02:02:21 +0530 Subject: [PATCH 06/13] grouped envs --- action.yml | 1 - src/config.py | 14 ++++++++++++++ src/groq_ai.py | 5 +++-- src/spell_check.py | 18 ++++++------------ 4 files changed, 23 insertions(+), 15 deletions(-) create mode 100644 src/config.py diff --git a/action.yml b/action.yml index b0e293a..c45db99 100644 --- a/action.yml +++ b/action.yml @@ -49,5 +49,4 @@ runs: GROQ_API_KEY: ${{ inputs.GROQ_API_KEY }} token: ${{ inputs.token }} PR_NO: ${{ github.event.pull_request.number }} - repo: $GITHUB_REPOSITORY run: python src/spell_check.py diff --git a/src/config.py b/src/config.py new file mode 100644 index 0000000..44b2b63 --- /dev/null +++ b/src/config.py @@ -0,0 +1,14 @@ +import os + + +def get_env(x): + return os.environ[x] + + +GROQ_API_KEY = get_env("GROQ_API_KEY") +PAT_TOKEN = get_env("token") + +REPO = get_env("GITHUB_REPOSITORY") +PR_BASE = get_env("PR_BASE") +PR_NO = get_env("PR_NO") +INPUT_FILES = [*map(str.strip, get_env("INPUT_FILES").splitlines())] diff --git a/src/groq_ai.py b/src/groq_ai.py index f337809..ea8450f 100644 --- a/src/groq_ai.py +++ b/src/groq_ai.py @@ -1,15 +1,16 @@ import json -import os from functools import cache from groq import NOT_GIVEN, BadRequestError, Groq +from src.config import GROQ_API_KEY + model = ["llama-3.1-8b-instant", "llama3-70b-8192"][1] @cache def get_groq_client(): - return Groq(api_key=os.environ.get("GROQ_API_KEY")) + return Groq(api_key=GROQ_API_KEY) def ask_groq(query_text: str, system_content: str, json_schema: dict = None) -> dict: diff --git a/src/spell_check.py b/src/spell_check.py index 833bcef..17d4740 100644 --- a/src/spell_check.py +++ b/src/spell_check.py @@ -1,12 +1,12 @@ -import os import subprocess import requests +from config import INPUT_FILES, PAT_TOKEN, PR_BASE, PR_NO, REPO from groq_ai import find_typos -def process_diff(file_path, base_branch): +def process_diff(file_path, base_branch=PR_BASE): try: # Get diff from PR diff_command = f"git diff -U0 origin/{base_branch}... -- {file_path}" @@ -21,12 +21,10 @@ def process_diff(file_path, base_branch): def post_comment(comment): - pr_no = os.environ["PR_NO"] - repo = os.environ["repo"] - url = f"https://api.github.com/repos/{repo}/issues/{pr_no}/comments" + url = f"https://api.github.com/repos/{REPO}/issues/{PR_NO}/comments" headers = { "Accept": "application/vnd.github+json", - "Authorization": f"Bearer {os.environ['token']}", + "Authorization": f"Bearer {PAT_TOKEN}", "X-GitHub-Api-Version": "2022-11-28", } resp = requests.post(url, headers=headers, json={"body": comment}) @@ -34,12 +32,8 @@ def post_comment(comment): def main(): - # Get required inputs - pr_base = os.environ["PR_BASE"] - files = [*map(str.strip, os.environ["INPUT_FILES"].splitlines())] - print(pr_base, *files, sep="\n") - - results = {file_path: process_diff(file_path, pr_base) for file_path in files if file_path} + # Process diff(s) for each file + results = {file_path: process_diff(file_path) for file_path in INPUT_FILES if file_path} # Create markdown comment for fixes flag = False From bc7558fc22f4b86155e944bf1c622699d50ceb11 Mon Sep 17 00:00:00 2001 From: rsb-23 <57601627+rsb-23@users.noreply.github.com> Date: Mon, 2 Dec 2024 02:17:52 +0530 Subject: [PATCH 07/13] fixing import --- local_test.py | 12 ++++-------- src/__init__.py | 0 src/groq_ai.py | 6 ++++-- src/spell_check.py | 4 ++-- 4 files changed, 10 insertions(+), 12 deletions(-) create mode 100644 src/__init__.py diff --git a/local_test.py b/local_test.py index 291c8a7..56bb2e9 100644 --- a/local_test.py +++ b/local_test.py @@ -1,12 +1,8 @@ -from src.spell_check import main +from dotenv import load_dotenv +load_dotenv() -def run(): - from dotenv import load_dotenv +if __name__ == "__main__": + from src.spell_check import main - load_dotenv() main() - - -if __name__ == "__main__": - run() diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/groq_ai.py b/src/groq_ai.py index ea8450f..5fc7e89 100644 --- a/src/groq_ai.py +++ b/src/groq_ai.py @@ -26,17 +26,19 @@ def ask_groq(query_text: str, system_content: str, json_schema: dict = None) -> response_format=response_format, ) json_str = chat_completion.choices[0].message.content + json_str = json_str.strip() except BadRequestError as e: failed_json = e.body["error"]["failed_generation"] # noqa json_str = failed_json.replace('"""', '"').replace("\n", "\\n") if not json_schema: return json_str try: - return json.loads(json_str.replace("\n", "")) + # json_str = re.sub("\n +", "", json_str) + return json.loads(json_str) except json.JSONDecodeError as e: print(e.doc, e.pos) print(f"ERROR : {e.args}") - return {"suggestions": "..."} + return {"suggestions": ["..."]} def find_typos(query_text): diff --git a/src/spell_check.py b/src/spell_check.py index 17d4740..412c69c 100644 --- a/src/spell_check.py +++ b/src/spell_check.py @@ -2,8 +2,8 @@ import requests -from config import INPUT_FILES, PAT_TOKEN, PR_BASE, PR_NO, REPO -from groq_ai import find_typos +from src.config import INPUT_FILES, PAT_TOKEN, PR_BASE, PR_NO, REPO +from src.groq_ai import find_typos def process_diff(file_path, base_branch=PR_BASE): From 9d3777c1f5a99facc5e261825498133aa4d1b8c5 Mon Sep 17 00:00:00 2001 From: rsb-23 <57601627+rsb-23@users.noreply.github.com> Date: Mon, 2 Dec 2024 02:19:59 +0530 Subject: [PATCH 08/13] adding venv --- action.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/action.yml b/action.yml index c45db99..87837c7 100644 --- a/action.yml +++ b/action.yml @@ -32,6 +32,8 @@ runs: cache: 'pip' - name: Setup python env run: | + python -m venv .venv + source venv/bin/activate python -m pip install --upgrade pip pip install -r requirements.txt shell: bash From 11f53d97aae7ae7eddd6d419cb6807f01295cb50 Mon Sep 17 00:00:00 2001 From: rsb-23 <57601627+rsb-23@users.noreply.github.com> Date: Mon, 2 Dec 2024 02:21:59 +0530 Subject: [PATCH 09/13] dot --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 87837c7..3f724f5 100644 --- a/action.yml +++ b/action.yml @@ -33,7 +33,7 @@ runs: - name: Setup python env run: | python -m venv .venv - source venv/bin/activate + source .venv/bin/activate python -m pip install --upgrade pip pip install -r requirements.txt shell: bash From c0e27edb5368ff970db1ec63e66175ce4e9ecc2a Mon Sep 17 00:00:00 2001 From: rsb-23 <57601627+rsb-23@users.noreply.github.com> Date: Mon, 2 Dec 2024 02:28:18 +0530 Subject: [PATCH 10/13] path error debug --- action.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 3f724f5..a826720 100644 --- a/action.yml +++ b/action.yml @@ -32,6 +32,7 @@ runs: cache: 'pip' - name: Setup python env run: | + pwd python -m venv .venv source .venv/bin/activate python -m pip install --upgrade pip @@ -51,4 +52,7 @@ runs: GROQ_API_KEY: ${{ inputs.GROQ_API_KEY }} token: ${{ inputs.token }} PR_NO: ${{ github.event.pull_request.number }} - run: python src/spell_check.py + run: | + pwd + source .venv/bin/activate + python src/spell_check.py From aa1e37b1c8571e3fea8081e2e420142bf051b4dd Mon Sep 17 00:00:00 2001 From: rsb-23 <57601627+rsb-23@users.noreply.github.com> Date: Mon, 2 Dec 2024 02:34:43 +0530 Subject: [PATCH 11/13] trying main file --- action.yml | 2 +- main.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 main.py diff --git a/action.yml b/action.yml index a826720..5cfea25 100644 --- a/action.yml +++ b/action.yml @@ -55,4 +55,4 @@ runs: run: | pwd source .venv/bin/activate - python src/spell_check.py + python main.py diff --git a/main.py b/main.py new file mode 100644 index 0000000..fb8beb2 --- /dev/null +++ b/main.py @@ -0,0 +1,4 @@ +from src.spell_check import main + +if __name__ == "__main__": + main() From 1312cc3eeabe432191c647fd0949568972b4bce0 Mon Sep 17 00:00:00 2001 From: rsb-23 <57601627+rsb-23@users.noreply.github.com> Date: Mon, 2 Dec 2024 02:55:52 +0530 Subject: [PATCH 12/13] Final nail --- .github/workflows/test.yml | 1 - README.md | 16 ++++++++++++++++ action.yml | 20 +++++++------------- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0f9370a..8a2a083 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,7 +12,6 @@ jobs: fetch-depth: 0 - name: Run script - id: spelling uses: ./ with: token: ${{ secrets.PAT }} diff --git a/README.md b/README.md index e69de29..ac362c9 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,16 @@ +# actions/check-typo + +This Github Action uses AI to find typos and grammatical errors in PR changes. + +## Usage +Refer [test.yml](./.github/workflows/test.yml) +```yaml + - name: Check typos in data files + uses: actions/check-diff-typo@v1 + with: + token: ${{ secrets.PAT }} + files: | + tests/file.txt + tests/file.json + GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }} +``` diff --git a/action.yml b/action.yml index 5cfea25..6fd5c6a 100644 --- a/action.yml +++ b/action.yml @@ -1,11 +1,15 @@ -name: 'Check-Diff-Typo' -description: 'Analyzes and comments on PR diff typos for specified files' +name: 'Check-Typo' +description: 'Checks diff of specified files for typos and suggests fixes on PR.' author: 'Rishabh B' branding: icon: 'git-pull-request' color: 'green' inputs: + token: + description: 'PAT with `pull_request:write` permission' + required: true + default: ${{ github.token }} files: description: 'Comma-separated list of files to analyze' required: true @@ -13,15 +17,7 @@ inputs: GROQ_API_KEY: description: 'Groq API Key' required: true - token: - description: 'PAT with pull_request:write permission' - required: true - default: ${{ github.token }} -outputs: - comment: - description: 'Generated comment markdown' - value: ${{ steps.spelling.outputs.comment }} runs: using: "composite" @@ -32,7 +28,6 @@ runs: cache: 'pip' - name: Setup python env run: | - pwd python -m venv .venv source .venv/bin/activate python -m pip install --upgrade pip @@ -47,12 +42,11 @@ runs: id: spelling shell: bash env: - PR_BASE: ${{ github.event.pull_request.base.ref }} + PR_BASE: ${{ github.base_ref }} INPUT_FILES: ${{ inputs.files }} GROQ_API_KEY: ${{ inputs.GROQ_API_KEY }} token: ${{ inputs.token }} PR_NO: ${{ github.event.pull_request.number }} run: | - pwd source .venv/bin/activate python main.py From 33f6b0eb95ef9c106064be324431607911f7a31a Mon Sep 17 00:00:00 2001 From: rsb-23 <57601627+rsb-23@users.noreply.github.com> Date: Mon, 2 Dec 2024 03:18:36 +0530 Subject: [PATCH 13/13] for debug --- src/groq_ai.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/groq_ai.py b/src/groq_ai.py index 5fc7e89..4348089 100644 --- a/src/groq_ai.py +++ b/src/groq_ai.py @@ -36,7 +36,7 @@ def ask_groq(query_text: str, system_content: str, json_schema: dict = None) -> # json_str = re.sub("\n +", "", json_str) return json.loads(json_str) except json.JSONDecodeError as e: - print(e.doc, e.pos) + print(e.doc.encode(), e.pos) print(f"ERROR : {e.args}") return {"suggestions": ["..."]}