Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 83 additions & 23 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ inputs:
build-delay:
description: Time to wait for docker container build
default: 50s
github-token:
description: GitHub token for PR interactions
required: false
default: ${{ github.token }}

runs:
using: "composite"
Expand All @@ -34,32 +38,61 @@ runs:
echo "${{ github.action_path }}" >> $GITHUB_PATH
echo "${{ inputs.working-directory }}"
shell: bash
- name: Grant permissions
run: chmod +x ${GITHUB_ACTION_PATH}/install.sh

- name: Grant permissions to scripts
run: |
chmod +x ${GITHUB_ACTION_PATH}/install.sh ${GITHUB_ACTION_PATH}/detect-languages.sh ${GITHUB_ACTION_PATH}/analyze-code.sh ${GITHUB_ACTION_PATH}/parse-results.sh
shell: bash

- id: keploy-test-report
name: Run Script
run: |
${GITHUB_ACTION_PATH}/install.sh > ${GITHUB_WORKSPACE}/${WORKDIR}/report.txt
cat ${GITHUB_WORKSPACE}/${WORKDIR}/report.txt

# Search for the complete testrun summary and extract total tests, total test passed, and total test failed data
grep -oE "COMPLETE TESTRUN SUMMARY\.\s+Total tests: [0-9]+" ${GITHUB_WORKSPACE}/${WORKDIR}/report.txt | sed -r "s/\x1B\[[0-9;]*[mGK]//g" > ${GITHUB_WORKSPACE}/${WORKDIR}/final_total_tests.out
grep -oE "COMPLETE TESTRUN SUMMARY\.\s+Total test passed: [0-9]+" ${GITHUB_WORKSPACE}/${WORKDIR}/report.txt | sed -r "s/\x1B\[[0-9;]*[mGK]//g" > ${GITHUB_WORKSPACE}/${WORKDIR}/final_total_passed.out
grep -oE "COMPLETE TESTRUN SUMMARY\.\s+Total test failed: [0-9]+" ${GITHUB_WORKSPACE}/${WORKDIR}/report.txt | sed -r "s/\x1B\[[0-9;]*[mGK]//g" > ${GITHUB_WORKSPACE}/${WORKDIR}/final_total_failed.out

# Combine the results into a single file and prepare output
cat ${GITHUB_WORKSPACE}/${WORKDIR}/final_total_tests.out ${GITHUB_WORKSPACE}/${WORKDIR}/final_total_passed.out ${GITHUB_WORKSPACE}/${WORKDIR}/final_total_failed.out > ${GITHUB_WORKSPACE}/${WORKDIR}/final.out
echo 'KEPLOY_REPORT<<EOF' > $GITHUB_OUTPUT
cat ${GITHUB_WORKSPACE}/${WORKDIR}/final.out >> $GITHUB_OUTPUT
echo 'EOF' >> $GITHUB_OUTPUT
cat $GITHUB_OUTPUT
name: Run Keploy Tests
run: ${GITHUB_ACTION_PATH}/install.sh > ${GITHUB_WORKSPACE}/${WORKDIR}/report.txt
shell: bash
env:
WORKDIR: ${{ inputs.working-directory }}
DELAY: ${{ inputs.delay }}
COMMAND : ${{ inputs.command }}
COMMAND: ${{ inputs.command }}
KEPLOY_PATH: ${{inputs.keploy-path}}

- name: Parse Test Results
id: parse-results
run: ${GITHUB_ACTION_PATH}/parse-results.sh
shell: bash
env:
WORKDIR: ${{ inputs.working-directory }}

- name: Fetch PR changes
id: pr-files
uses: actions/github-script@v6
with:
github-token: ${{ inputs.github-token }}
script: |
try {

@khareyash05 khareyash05 Mar 6, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets not make the yml file cluttered, encouraging to use shell files for same

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure Yash! I also took the chance to move the parsing to a new script as well

const response = await github.rest.pulls.listFiles({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
});
const files = response.data.map(file => file.filename);
core.setOutput('files', files.join(','));
return files;
} catch (error) {
core.setFailed(`Failed to fetch PR files: ${error.message}`);
}

- name: Detect languages
id: language-detection
run: ${GITHUB_ACTION_PATH}/detect-languages.sh
shell: bash

- name: Run code analysis
run: ${GITHUB_ACTION_PATH}/analyze-code.sh
shell: bash
env:
WORKDIR: ${{ inputs.working-directory }}
DETECTED_LANGUAGES: ${{ steps.language-detection.outputs.languages }}
PR_FILES: ${{ steps.pr-files.outputs.files }}

- name: Check if report is generated
run: |
if [ -s ${GITHUB_WORKSPACE}/${WORKDIR}/final.out ]; then
Expand All @@ -69,21 +102,48 @@ runs:
exit 1
fi
shell: bash
env:
WORKDIR: ${{ inputs.working-directory }}

- name: Comment on PR
if: success()
uses: actions/github-script@v6
env:
KEPLOY_REPORT: ${{ steps.keploy-test-report.outputs.KEPLOY_REPORT }}
KEPLOY_REPORT: ${{ steps.parse-results.outputs.KEPLOY_REPORT }}
with:
github-token: ${{ github.token }}
github-token: ${{ inputs.github-token }}
script: |
if (!process.env.KEPLOY_REPORT) {
console.error('Error: KEPLOY_REPORT not found.');
process.exit(1);
}

const fs = require('fs');
const path = require('path');

function readReport(filepath) {
try {
return fs.readFileSync(filepath, 'utf8');
} catch (error) {
return null;
}
}

const reportsDir = path.join('${{ inputs.working-directory }}', 'analysis-reports');
const reports = fs.readdirSync(reportsDir)
.filter(file => file.endsWith('.txt') || file.endsWith('.xml'))
.map(file => readReport(path.join(reportsDir, file)))
.filter(Boolean);

const summary = `## 📊 TestGPT Analysis Report

${process.env.KEPLOY_REPORT || 'No test results available'}

${reports.join('\n\n')}`;

github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: process.env.KEPLOY_REPORT
})
body: summary
})
140 changes: 140 additions & 0 deletions analyze-code.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#!/bin/bash

# Change to the workspace directory
cd $GITHUB_WORKSPACE/$WORKDIR

# Ensure analysis-reports directory exists
mkdir -p analysis-reports

# Function to find existing linter installations
find_linter() {
local linter_name=$1
local system_path=$(which $linter_name 2>/dev/null)
echo $system_path
}

# Log message function
log_message() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

log_message "Starting code analysis"

for lang in $DETECTED_LANGUAGES; do
case "$lang" in
go)
GO_LINTER=$(find_linter golangci-lint)
if [ -z "$GO_LINTER" ]; then
log_message "Installing golangci-lint..."
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
else
log_message "Using system golangci-lint: $GO_LINTER"
fi
;;
javascript)
JS_LINTER=$(find_linter eslint)
if [ -z "$JS_LINTER" ]; then
log_message "Installing eslint..."
npm install -g eslint
else
log_message "Using system eslint: $JS_LINTER"
fi
;;
python)
PY_LINTER=$(find_linter flake8)
PY_SECURITY=$(find_linter bandit)
if [ -z "$PY_LINTER" ]; then
log_message "Installing flake8..."
pip install flake8
else
log_message "Using system flake8: $PY_LINTER"
fi
if [ -z "$PY_SECURITY" ]; then
log_message "Installing bandit..."
pip install bandit
else
log_message "Using system bandit: $PY_SECURITY"
fi
;;
esac
done

if [ -n "$PR_FILES" ]; then
IFS=',' read -ra FILES <<< "$PR_FILES"

for lang in $DETECTED_LANGUAGES; do
case "$lang" in
go)
GO_FILES=()
for file in "${FILES[@]}"; do
if [[ $file == *.go ]]; then
GO_FILES+=("$file")
fi
done
if [ ${#GO_FILES[@]} -gt 0 ]; then
golangci-lint run --out-format=github-actions "${GO_FILES[@]}" > analysis-reports/go-lint.txt 2>&1 || true
else
echo "No Go files changed in PR" > analysis-reports/go-lint.txt
fi
;;
javascript)
JS_FILES=()
for file in "${FILES[@]}"; do
if [[ $file == *.js || $file == *.ts || $file == *.jsx || $file == *.tsx ]]; then
JS_FILES+=("$file")
fi
done
if [ ${#JS_FILES[@]} -gt 0 ] && ([ -f ".eslintrc.js" ] || [ -f ".eslintrc.json" ] || [ -f ".eslintrc.yml" ]); then
eslint "${JS_FILES[@]}" --format junit -o analysis-reports/js-lint.xml 2>&1 || true
else
echo "No JavaScript/TypeScript files changed in PR or no ESLint config found" > analysis-reports/js-lint.txt
fi
;;
python)
PY_FILES=()
for file in "${FILES[@]}"; do
if [[ $file == *.py ]]; then
PY_FILES+=("$file")
fi
done
if [ ${#PY_FILES[@]} -gt 0 ]; then
flake8 "${PY_FILES[@]}" --output-file=analysis-reports/py-lint.txt 2>&1 || true
bandit -r "${PY_FILES[@]}" -f txt -o analysis-reports/py-security.txt 2>&1 || true
else
echo "No Python files changed in PR" > analysis-reports/py-lint.txt
fi
;;
esac
done
else
for lang in $DETECTED_LANGUAGES; do
case "$lang" in
go)
golangci-lint run --out-format=github-actions ./... > analysis-reports/go-lint.txt 2>&1 || true
;;
javascript)
if [ -f ".eslintrc.js" ] || [ -f ".eslintrc.json" ] || [ -f ".eslintrc.yml" ]; then
eslint . --format junit -o analysis-reports/js-lint.xml 2>&1 || true
else
echo "No ESLint config found, skipping JavaScript linting" > analysis-reports/js-lint.txt
fi
;;
python)
flake8 . --output-file=analysis-reports/py-lint.txt 2>&1 || true
bandit -r . -f txt -o analysis-reports/py-security.txt 2>&1 || true
;;
esac
done
fi

temp_file=$(mktemp)
for report in analysis-reports/*; do
if [ -f "$report" ]; then
echo "### $(basename "$report")" >> "$temp_file"
cat "$report" >> "$temp_file"
echo -e "\n---\n" >> "$temp_file"
fi
done
mv "$temp_file" analysis-reports/final-report.txt

log_message "Code analysis completed"
32 changes: 32 additions & 0 deletions detect-languages.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/bash

declare -A extensions=(
["go"]="go"
["js"]="javascript"
["ts"]="javascript"
["jsx"]="javascript"
["tsx"]="javascript"
["py"]="python"
["java"]="java"
)

LANGUAGES=""

# Exclude common non-source files
while IFS= read -r file; do
ext="${file##*.}"
Comment thread
Hermione2408 marked this conversation as resolved.
if [[ -n "${extensions[$ext]}" ]]; then
LANGUAGES+="${extensions[$ext]} "
fi
done < <(find . -type f \
-not -path "*/\.*/*" \
-not -path "*/node_modules/*" \
-not -path "*/dist/*" \
-not -path "*/build/*" \
-not -path "*/target/*" \
-not -path "*/vendor/*" \
-not -path "*/__pycache__/*" \
-size -1M)

UNIQUE_LANGS=$(echo "$LANGUAGES" | tr ' ' '\n' | sort -u | tr '\n' ' ')
echo "languages=$UNIQUE_LANGS" >> $GITHUB_OUTPUT
23 changes: 23 additions & 0 deletions parse-results.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/bash

mkdir -p "${GITHUB_WORKSPACE}/${WORKDIR}"

ANSI_FILTER="s/\x1B\[([0-9]{1,3}(;[0-9]{1,3})*)?[mGK]//g"

if [ ! -f "${GITHUB_WORKSPACE}/${WORKDIR}/report.txt" ]; then
echo "ERROR: Test report file not found. Please ensure tests were executed correctly." > "${GITHUB_WORKSPACE}/${WORKDIR}/final.out"
else
Comment thread
Hermione2408 marked this conversation as resolved.
grep -oE "COMPLETE TESTRUN SUMMARY\.\s+Total tests: [0-9]+" "${GITHUB_WORKSPACE}/${WORKDIR}/report.txt" | sed -r "${ANSI_FILTER}" > "${GITHUB_WORKSPACE}/${WORKDIR}/final_total_tests.out"
grep -oE "COMPLETE TESTRUN SUMMARY\.\s+Total test passed: [0-9]+" "${GITHUB_WORKSPACE}/${WORKDIR}/report.txt" | sed -r "${ANSI_FILTER}" > "${GITHUB_WORKSPACE}/${WORKDIR}/final_total_passed.out"
grep -oE "COMPLETE TESTRUN SUMMARY\.\s+Total test failed: [0-9]+" "${GITHUB_WORKSPACE}/${WORKDIR}/report.txt" | sed -r "${ANSI_FILTER}" > "${GITHUB_WORKSPACE}/${WORKDIR}/final_total_failed.out"

if [ ! -s "${GITHUB_WORKSPACE}/${WORKDIR}/final_total_tests.out" ]; then
echo "ERROR: No valid test summary found in report file. Please check test execution output format." > "${GITHUB_WORKSPACE}/${WORKDIR}/final.out"
else
cat "${GITHUB_WORKSPACE}/${WORKDIR}/final_total_tests.out" "${GITHUB_WORKSPACE}/${WORKDIR}/final_total_passed.out" "${GITHUB_WORKSPACE}/${WORKDIR}/final_total_failed.out" > "${GITHUB_WORKSPACE}/${WORKDIR}/final.out"
fi
fi

echo 'KEPLOY_REPORT<<EOF' >> $GITHUB_OUTPUT
cat "${GITHUB_WORKSPACE}/${WORKDIR}/final.out" >> $GITHUB_OUTPUT
echo 'EOF' >> $GITHUB_OUTPUT