Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Johnnyevans32 committed Nov 18, 2024
2 parents 16e2afc + 01cb4e2 commit d8611f9
Show file tree
Hide file tree
Showing 11 changed files with 469 additions and 20 deletions.
72 changes: 56 additions & 16 deletions .github/workflows/update-loosegoose-leaderboard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,15 @@ jobs:
];
const calculatePoints = (labels) => {
return 10;
const labelNames = labels.map(label => label.name.toLowerCase());
const hasLooseGoose = labelNames.includes('loosegoose');
const hasCode = labelNames.includes('code');
return {
points: hasLooseGoose && hasCode ? 15 : (hasLooseGoose ? 10 : 0),
isCodePR: hasCode,
isContentPR: hasLooseGoose && !hasCode
};
};
const fetchRecentPRs = async (repo) => {
Expand All @@ -55,13 +63,18 @@ jobs:
const isRecent = new Date(pr.merged_at) > new Date(thirtyDaysAgo);
const isLoosegoose = pr.labels.some(label => label.name.toLowerCase() === 'loosegoose');
return isMerged && isRecent && isLoosegoose;
}).map(pr => ({
user: pr.user.login,
points: calculatePoints(pr.labels),
repo: repo,
prNumber: pr.number,
prTitle: pr.title,
}));
}).map(pr => {
const pointsData = calculatePoints(pr.labels);
return {
user: pr.user.login,
points: pointsData.points,
isCodePR: pointsData.isCodePR,
isContentPR: pointsData.isContentPR,
repo: repo,
prNumber: pr.number,
prTitle: pr.title,
};
});
return loosegoosePRs;
} catch (error) {
console.error(`Error fetching PRs for ${repo}: ${error.message}`);
Expand All @@ -74,9 +87,22 @@ jobs:
const allPRs = await Promise.all(REPOS.map(fetchRecentPRs));
const flatPRs = allPRs.flat();
const leaderboard = flatPRs.reduce((acc, pr) => {
if (!acc[pr.user]) acc[pr.user] = { points: 0, prs: 0 };
if (!acc[pr.user]) {
acc[pr.user] = {
points: 0,
prs: 0,
codePRs: 0,
contentPRs: 0
};
}
acc[pr.user].points += pr.points;
acc[pr.user].prs += 1;
if (pr.isCodePR) {
acc[pr.user].codePRs += 1;
}
if (pr.isContentPR) {
acc[pr.user].contentPRs += 1;
}
return acc;
}, {});
Expand All @@ -86,7 +112,9 @@ jobs:
rank: index + 1,
username,
points: data.points,
prs: data.prs
prs: data.prs,
codePRs: data.codePRs,
contentPRs: data.contentPRs
}));
} catch (error) {
console.error(`Error generating leaderboard: ${error.message}`);
Expand All @@ -97,7 +125,7 @@ jobs:
const updateIssue = async (leaderboardData) => {
try {
const rows = leaderboardData.map(entry =>
`| ${entry.rank} | @${entry.username} | ${entry.points} | ${entry.prs} |`
`| ${entry.rank} | @${entry.username} | ${entry.points} | ${entry.prs} | ${entry.codePRs} | ${entry.contentPRs} |`
).join('\n');
const issueBody = [
Expand All @@ -106,18 +134,23 @@ jobs:
'',
'## This event is open to both employees and external contributors! 🦢',
'### 🌟 **Current Rankings:**',
'| Rank | Contributor | Points | PRs |',
'|------|-------------|--------|-----|',
'| Rank | Contributor | Points | Total PRs | Code PRs | Content PRs |',
'|------|-------------|--------|-----------|-----------|-------------|',
rows,
'',
'### 📜 How It Works:',
'The top 3 contributors with the most points will earn $$$ gift cards (more on rewards below). To earn your place in the leaderboard, you want to close the most PRs to earn the most points. As you complete a task by successfully merging a PR, you will automatically be granted 10 points per task completed.',
'The top 3 contributors with the most points will earn $$$ gift cards (more on rewards below). Points are awarded based on the following criteria:',
'- 15 points for each merged PR with both `loosegoose` and `code` labels',
'- 10 points for each merged PR with just the `loosegoose` label (Content PR)',
'',
'### 🎁 Rewards',
'- Among our **top 3**? Our Top 3 Superstars earn $150 gift cards on Amazon. Stay tuned for the winners!',
'',
'### FAQ',
'- **Frequency of Updates:** The leaderboard will be updated every 1 hour.',
'- **Points System:**',
' - 15 points: Code PRs (PRs with both `loosegoose` and `code` labels)',
' - 10 points: Content PRs (PRs with just the `loosegoose` label)',
'- **Criteria:** Rankings are based on how many points you earn and PRs you close in the goose-plugins repo. To ensure your PRs are successfully merged:',
' - Ensure your contributions are aligned with our [project\'s CoC](https://github.com/block-open-source/goose-plugins/blob/main/CODE_OF_CONDUCT.md).',
' - Refer to our [Contributing Guide](https://github.com/block-open-source/goose-plugins/blob/main/CONTRIBUTING.md).',
Expand Down Expand Up @@ -156,16 +189,23 @@ jobs:
'',
'## This event is open to both employees and external contributors! 🦢',
'### 🌟 **Current Rankings:**',
'| Rank | Contributor | Points | Total PRs | Code PRs | Content PRs |',
'|------|-------------|--------|-----------|-----------|-------------|',
'No qualifying PRs found at this time. Check back soon!',
'',
'### 📜 How It Works:',
'The top 3 contributors with the most points will earn $$$ gift cards (more on rewards below). To earn your place in the leaderboard, you want to close the most PRs to earn the most points. As you complete a task by successfully merging a PR, you will automatically be granted 10 points per task completed.',
'The top 3 contributors with the most points will earn $$$ gift cards (more on rewards below). Points are awarded based on the following criteria:',
'- 15 points for each merged PR with both `loosegoose` and `code` labels (Code PR)',
'- 10 points for each merged PR with just the `loosegoose` label (Content PR)',
'',
'### 🎁 Rewards',
'- Among our **top 3**? Our Top 3 Superstars earn $150 gift cards on Amazon. Stay tuned for the winners!',
'',
'### FAQ',
'- **Frequency of Updates:** The leaderboard will be updated every 1 hour.',
'- **Points System:**',
' - 15 points: Code PRs (PRs with both `loosegoose` and `code` labels)',
' - 10 points: Content PRs (PRs with just the `loosegoose` label)',
'- **Criteria:** Rankings are based on how many points you earn and PRs you close in the goose-plugins repo. To ensure your PRs are successfully merged:',
' - Ensure your contributions are aligned with our [project\'s CoC](https://github.com/block-open-source/goose-plugins/blob/main/CODE_OF_CONDUCT.md).',
' - Refer to our [Contributing Guide](https://github.com/block-open-source/goose-plugins/blob/main/CONTRIBUTING.md).',
Expand All @@ -186,4 +226,4 @@ jobs:
body: emptyIssueBody
});
console.log("Updated issue with empty leaderboard message.");
}
}
29 changes: 25 additions & 4 deletions content/content.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@
"link": "https://x.com/kirantweets99/status/1857436757307867594",
"contributor": "Kiran Baliga"
},
{
"type": "social",
"thumbnail": "./img/gooseopenai.png",
"title": "Using Goose with OpenAI",
"link": "https://x.com/kirantweets99/status/1857800570574352500",
"contributor": "Kiran Baliga"
},
{
"type": "blog",
"thumbnail": "https://dev-to-uploads.s3.amazonaws.com/uploads/articles/73stdcqp8ek29digbsj1.png",
Expand All @@ -72,7 +79,7 @@
},
{
"type": "blog",
"thumbnail": "./img/using goose as a github action.png",
"thumbnail": "./img/using-goose-as-a-github-action.png",
"title": "Using Goose as a GitHub Action",
"link": "https://dev.to/lymah/using-goose-as-a-github-action-h4n",
"contributor": "Lymah123"
Expand Down Expand Up @@ -100,9 +107,23 @@
},
{
"type": "short",
"thumbnail": "./img/using-goose-as-a-github-action.png",
"title": ""
"link": "Using Goose as a GitHub Action",
"thumbnail": "./img/use-goose-as-github-action-shorts.png",
"title": "Using Goose as a GitHub Action Shorts",
"link": "https://www.youtube.com/watch?v=kQbhxZUOUxw",
"contributor": "Lymah123"
},
{
"type": "short",
"thumbnail": "./img/using-goose-as-a-github action-reel.png",
"title": "Using Goose as a GitHub Action Reel",
"link": "https://www.instagram.com/lymahcodes/reel/DCU7jpUATOJ/",
"contributor": "Lymah123"
},
{
"type": "blog",
"thumbnail": "./img/how-to-set-up-goose-on-windows.png",
"title": "How to Set Up Goose on Windows",
"link": "https://dev.to/lymah/how-to-set-up-goose-on-windows-29dd",
"contributor": "Lymah123"
}
]
Expand Down
Binary file added content/img/gooseopenai.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/img/how-to-set-up-goose-on-windows.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/img/use-goose-as-github-action-shorts.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ requires-python = ">=3.10"
dependencies = [
"ai-exchange>=0.8.4",
"goose-ai>=0.9.8",
"radon>=6.0.1",
]
author = [{ name = "Block", email = "[email protected]" }]
packages = [{ include = "goose_plugins", from = "src" }]
Expand All @@ -20,6 +21,8 @@ goose-plugins = "goose_plugins:module_name"
[project.entry-points."goose.toolkit"]
artify = "goose_plugins.toolkits.artify:VincentVanCode"
todo = "goose_plugins.toolkits.todo:TodoToolkit"
complexity_analyzer = "goose_plugins.toolkits.complexity_analyzer:CodeComplexityToolkit"
dockerize_my_app = "goose_plugins.toolkits.dockerize_my_app:DockerizationToolkit"
filetype_analyzer = "goose_plugins.toolkits.filetype_analyzer:FileTypeAnalyzerToolkit"


Expand Down
156 changes: 156 additions & 0 deletions src/goose_plugins/toolkits/complexity_analyzer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import os
import ast
from goose.toolkit.base import Toolkit, tool
from radon.complexity import cc_visit
from radon.metrics import h_visit, mi_visit


class CodeComplexityToolkit(Toolkit):
"""A toolkit for analyzing the complexity of Python code in a given directory."""

def __init__(self, *args: tuple, **kwargs: dict) -> None:
super().__init__(*args, **kwargs)

@tool
def get_python_files(self, directory: str) -> list:
"""Retrieve all Python files from the specified directory.
Args:
directory (str): The directory to search for Python files.
Returns:
list: A list of paths to all Python files in the directory.
"""
return [
os.path.join(root, file) for root, _, files in os.walk(directory) for file in files if file.endswith(".py")
]

@tool
def analyze_complexity(self, directory: str) -> dict:
"""Analyze the complexity of Python code in a directory.
Args:
directory (str): The path to the directory containing Python files to analyze.
Returns:
dict: A dictionary containing the average complexity metrics (Cyclomatic Complexity, Halstead Metrics,
and Maintainability Index) for all Python files in the directory, or an error message if no
valid Python files are found.
"""
python_files = self.get_python_files(directory)
if not python_files:
return {"error": f"No Python files found in the directory: {directory}"}

complexity_results = {
"cyclomatic_complexity": 0,
"halstead_metrics": 0,
"maintainability_index": 0,
"file_count": 0,
}

for file in python_files:
try:
with open(file, "r", encoding="utf-8") as f:
code = f.read()

# Process each complexity metric and update the results
complexity_results["cyclomatic_complexity"] += self.cyclomatic_complexity(code)
halstead_result = self.halstead_complexity(code)
complexity_results["halstead_metrics"] += halstead_result["halstead_volume"] if halstead_result else 0
complexity_results["maintainability_index"] += self.maintainability_index(code)
complexity_results["file_count"] += 1

except Exception as e:
complexity_results["error"] = f"Error processing {file}: {str(e)}"
continue

if complexity_results["file_count"] > 0:
# Average the results
return {
"avg_cyclomatic_complexity": complexity_results["cyclomatic_complexity"]
/ complexity_results["file_count"],
"avg_halstead_complexity": complexity_results["halstead_metrics"] / complexity_results["file_count"],
"avg_maintainability_index": complexity_results["maintainability_index"]
/ complexity_results["file_count"],
}
else:
return {"error": "No valid Python files to analyze."}

@tool
def cyclomatic_complexity(self, code: str) -> int:
"""Calculate the Cyclomatic Complexity of a given Python code.
Args:
code (str): The Python code as a string to analyze.
Returns:
int: The Cyclomatic Complexity of the code.
"""
try:
complexity_list = cc_visit(ast.parse(code))
total_complexity = 0

# Iterate over each item in the complexity list
for item in complexity_list:
if hasattr(item, "complexity"):
# Add complexity of the function or class's top-level complexity
total_complexity += item.complexity

# For classes, add complexity of methods if any
if hasattr(item, "methods"):
for method in item.methods:
total_complexity += method.complexity
return total_complexity
except Exception as e:
print(e)
self.notifier.log(f"Error calculating cyclomatic complexity: {str(e)}")
return 0

@tool
def halstead_complexity(self, code: str) -> dict:
"""Calculate Halstead Complexity metrics of the given Python code.
Args:
code (str): The Python code as a string to analyze.
Returns:
dict: A dictionary containing the Halstead metrics, including 'halstead_volume'.
"""

try:
halstead_report = h_visit(code)
return {
"halstead_volume": halstead_report.total.volume,
"details": {
"vocabulary": halstead_report.total.vocabulary,
"length": halstead_report.total.length,
"calculated_length": halstead_report.total.calculated_length,
"difficulty": halstead_report.total.difficulty,
"effort": halstead_report.total.effort,
"time": halstead_report.total.time,
"bugs": halstead_report.total.bugs,
},
}
except Exception as e:
print(e)
self.notifier.log(f"Error calculating Halstead complexity: {str(e)}")
return {}

@tool
def maintainability_index(self, code: str) -> int:
"""Calculate the Maintainability Index of the given Python code.
Args:
code (str): The Python code as a string to analyze.
Returns:
int: The Maintainability Index of the code.
"""

try:
mi_score = mi_visit(code, multi=True)
return mi_score
except Exception as e:
print(e)
self.notifier.log(f"Error calculating maintainability index: {str(e)}")
return 0
Loading

0 comments on commit d8611f9

Please sign in to comment.