From 5cfa9b2f2bc7841db251c73b130232232970b237 Mon Sep 17 00:00:00 2001 From: jordan-ae Date: Tue, 10 Sep 2024 21:00:23 +0100 Subject: [PATCH 1/2] feat: add empty string warning --- .github/workflows/empty-string-warning.yml | 67 +++++++++++++++++++ .../workflows/empty-strings/empty-strings.ts | 51 ++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 .github/workflows/empty-string-warning.yml create mode 100644 tests/workflows/empty-strings/empty-strings.ts diff --git a/.github/workflows/empty-string-warning.yml b/.github/workflows/empty-string-warning.yml new file mode 100644 index 0000000..6c8a983 --- /dev/null +++ b/.github/workflows/empty-string-warning.yml @@ -0,0 +1,67 @@ +name: Warn for Empty Strings + +on: + pull_request: + paths: + - "**/*.ts" + - "**/*.tsx" + +permissions: + issues: write + pull-requests: write + +jobs: + check-empty-strings: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Find empty strings in TypeScript files + id: find_empty_strings + run: | + # Find empty strings and mark them explicitly + output=$(grep -Pnr --include=\*.ts "(?> $GITHUB_OUTPUT + exit 0 + else + output=$(echo "$output" | sed 's/""/"[EMPTY STRING]"/g' | sed "s/''/'[EMPTY STRING]'/g") + echo "results=${output//$'\n'/%0A}" >> $GITHUB_OUTPUT + fi + + - name: findings + if: steps.find_empty_strings.outputs.results != 'No empty strings found.' + run: | + if [ "${{ steps.find_empty_strings.outputs.results }}" == "No empty strings found." ]; then + echo "No empty strings found. No action required." + else + echo "::warning::Empty strings found in the following files:" + echo "${{ steps.find_empty_strings.outputs.results }}" + fi + + - name: Post review comments for findings + if: steps.find_empty_strings.outputs.results != 'No empty strings found.' + uses: actions/github-script@v7 + with: + script: | + const findings = `${{ steps.find_empty_strings.outputs.results }}`.split('%0A'); + for (const finding of findings) { + const [path, line] = finding.split(':'); + const body = "Empty string detected!"; + const prNumber = context.payload.pull_request.number; + const owner = context.repo.owner; + const repo = context.repo.repo; + + await github.rest.pulls.createReviewComment({ + owner, + repo, + pull_number: prNumber, + body, + commit_id: context.payload.pull_request.head.sha, + path, + line: parseInt(line, 10), + }); + } diff --git a/tests/workflows/empty-strings/empty-strings.ts b/tests/workflows/empty-strings/empty-strings.ts new file mode 100644 index 0000000..b84bc32 --- /dev/null +++ b/tests/workflows/empty-strings/empty-strings.ts @@ -0,0 +1,51 @@ +export interface CheckEmptyStringsOptions { + readDir: (path: string) => Promise; + readFile: (path: string, encoding: string) => Promise; + ignorePatterns?: string[]; + } + + export async function checkForEmptyStringsInFiles( + dir: string, + options: CheckEmptyStringsOptions + ): Promise { + const { readDir, readFile, ignorePatterns = [] } = options; + const filesWithEmptyStrings: string[] = []; + const ignoreList: string[] = ["^\\.\\/\\.git", "^\\.\\/\\..*", "^\\.\\/node_modules", "^\\.\\/dist", "^\\.\\/out", ".*\\.test\\.ts$", ...ignorePatterns]; + + // Add .gitignore patterns + try { + const gitignoreContent = await readFile(".gitignore", "utf8"); + gitignoreContent.split("\n").forEach((line) => { + if (line.trim() && !line.startsWith("#")) { // Ignore comments and empty lines + ignoreList.push(`^\\.\\/${line.replace(/\./g, "\\.").replace(/\//g, "\\/")}`); + } + }); + } catch (error) { + console.error("Error reading .gitignore file:", error); + } + + try { + const files = await readDir(dir); + for (const fileName of files) { + let shouldIgnore = false; + for (const pattern of ignoreList) { + if (new RegExp(pattern).test(fileName)) { + shouldIgnore = true; + break; + } + } + if (shouldIgnore || !fileName.endsWith(".ts")) continue; + + const fileContent = await readFile(`${dir}/${fileName}`, "utf8"); + // Refined to match only standalone empty strings + if (fileContent.match(/(? Date: Tue, 10 Sep 2024 21:01:08 +0100 Subject: [PATCH 2/2] test: test workflow --- static/main.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/static/main.ts b/static/main.ts index 780e240..5ddfc6d 100644 --- a/static/main.ts +++ b/static/main.ts @@ -2,6 +2,9 @@ export async function mainModule() { console.log(`Hello from mainModule`); } +const testEmptyString = "" +const testEmptyStrings = '' + mainModule() .then(() => { console.log("mainModule loaded");