diff --git a/.github/workflows/clone-repos.yml b/.github/workflows/clone-repos.yml index a9de5f2..f2cac7f 100644 --- a/.github/workflows/clone-repos.yml +++ b/.github/workflows/clone-repos.yml @@ -47,6 +47,7 @@ jobs: import json import os import subprocess + import requests # Check if submissions.json exists if not os.path.exists("submissions.json"): @@ -59,6 +60,7 @@ jobs: os.makedirs("Submissions", exist_ok=True) new_repos_cloned = False + failed_clones = [] for submission in submissions: name = submission.get("name", "unknown") @@ -69,6 +71,30 @@ jobs: print(f"No repository URL found for {name}, skipping...") continue + # Check if repo is public and not too large + try: + parts = repo_url.rstrip("/").split("/") + owner, repo = parts[-2], parts[-1].replace('.git','') + api_url = f"https://api.github.com/repos/{owner}/{repo}" + resp = requests.get(api_url) + if resp.status_code != 200: + print(f"Repository {repo_url} is not accessible (status {resp.status_code}), skipping...") + failed_clones.append(repo_url) + continue + repo_info = resp.json() + if repo_info.get("private"): + print(f"Repository {repo_url} is private, skipping...") + failed_clones.append(repo_url) + continue + if repo_info.get("size", 0) > 100000: # ~100MB + print(f"Repository {repo_url} is too large (>100MB), skipping...") + failed_clones.append(repo_url) + continue + except Exception as e: + print(f"Error checking repo {repo_url}: {e}") + failed_clones.append(repo_url) + continue + clone_path = os.path.join("Submissions", project_name) if os.path.exists(clone_path): @@ -88,12 +114,25 @@ jobs: print(f"Successfully cloned {repo_url}") except subprocess.CalledProcessError as e: print(f"Failed to clone {repo_url}: {e}") + failed_clones.append(repo_url) if new_repos_cloned: with open(os.environ["GITHUB_ENV"], "a") as env_file: env_file.write("NEW_CLONES=true\n") + if failed_clones: + with open("clone_failures.txt", "w") as f: + for url in failed_clones: + f.write(url + "\n") ' + - name: Notify maintainers of failed clones + if: always() + run: | + if [ -f clone_failures.txt ]; then + echo "Some repositories failed to clone. Notifying maintainers." + gh issue create --title "Repository Clone Failures" --body "The following repositories could not be cloned during the last run:\n\n$(cat clone_failures.txt)" || true + fi + - name: Commit and Push Cloned Repositories if: env.NEW_CLONES == 'true' run: | diff --git a/.github/workflows/issue-to-submission.yml b/.github/workflows/issue-to-submission.yml index 8bf51ec..c4b6122 100644 --- a/.github/workflows/issue-to-submission.yml +++ b/.github/workflows/issue-to-submission.yml @@ -66,10 +66,30 @@ jobs: return; } + // Check for required headings to ensure template format + const requiredHeadings = [ + '### Name', + '### Project Name', + '### GitHub Repository URL', + '### Project Description' + ]; + for (const heading of requiredHeadings) { + if (!body.includes(heading)) { + core.setFailed('Issue template format has changed or is incomplete.'); + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + body: `❌ **Error:** The issue template format is incorrect or missing required headings. Please use the official submission template.` + }); + return; + } + } + const nameMatch = body.match(/### Name\s*\n\s*([^\n]+)/); const projectMatch = body.match(/### Project Name\s*\n\s*([^\n]+)/); const repoMatch = body.match(/### GitHub Repository URL\s*\n\s*([^\n]+)/); - const descMatch = body.match(/### Project Description\s*\n\s*([\s\S]*?)(?=###|$)/); + const descMatch = body.match(/### Project Description\s*\n*([\s\S]*?)(?=###|$)/); if (!nameMatch || !projectMatch || !repoMatch || !descMatch) { core.setFailed('Could not extract all required information from issue'); diff --git a/.github/workflows/merge-pr-on-issue-close.yml b/.github/workflows/merge-pr-on-issue-close.yml index d7972bb..1368ba9 100644 --- a/.github/workflows/merge-pr-on-issue-close.yml +++ b/.github/workflows/merge-pr-on-issue-close.yml @@ -113,21 +113,23 @@ jobs: git show origin/main:submissions.json > main_submissions.json || touch main_submissions.json git show "$PR_BRANCH":submissions.json > pr_submissions.json || touch pr_submissions.json - # Merge JSON contents (ensuring unique submissions by repository_url) - jq -s 'add | group_by(.repository_url) | map(if .[0].repository_url == "" then .[0] else .[] end)' main_submissions.json pr_submissions.json > submissions.json + # Merge JSON contents (ensuring unique submissions by repository_url and removing empty/invalid entries) + jq -s 'add | map(select(.repository_url and .name and .project_name and .description and (.repository_url|test("^https?://github\\.com/[\\w-]+/[\\w-]+(?:\\.git)?$"))) | unique_by(.repository_url)' main_submissions.json pr_submissions.json > submissions.json # Stage the resolved file git add submissions.json if git rebase --continue; then - echo "✅ Merge conflicts resolved, rebase successful." + echo "✅ Merge conflicts resolved, rebase successful." elif git status --porcelain | grep submissions.json; then - git add submissions.json - git commit -m "$PR_TITLE" - git rebase --continue + git add submissions.json + git commit -m "$PR_TITLE" + git rebase --continue else - echo "⚠️ Rebase still failing. Aborting..." - git rebase --abort - exit 1 + echo "⚠️ Rebase still failing. Aborting..." + git rebase --abort + # Notify maintainers of failure + gh issue comment "$ISSUE_NUMBER" --body "❌ Merge conflict in submissions.json could not be resolved automatically. Manual intervention required." + exit 1 fi fi diff --git a/.github/workflows/submission-validation.yml b/.github/workflows/submission-validation.yml index 801822e..64a1347 100644 --- a/.github/workflows/submission-validation.yml +++ b/.github/workflows/submission-validation.yml @@ -48,7 +48,8 @@ jobs: - name: Check if PR is Late id: deadline-check run: | - DEADLINE="2025-02-02T13:30:00Z" + # Read deadline from config.yml + DEADLINE=$(python3 -c 'import yaml; print(yaml.safe_load(open("config.yml"))["deadline"])' 2>/dev/null || python3 -c 'import sys, yaml; print(yaml.safe_load(sys.stdin)["deadline"])' < config.yml) CURRENT_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ") if [[ "$CURRENT_TIME" > "$DEADLINE" ]]; then @@ -68,13 +69,21 @@ jobs: python -c ' import json import sys + import re try: with open("submissions.json", "r") as f: submissions = json.load(f) required_keys = ["name", "project_name", "repository_url", "description"] + url_pattern = r"^https?://github\\.com/[\\w-]+/[\\w-]+(?:\\.git)?$" for submission in submissions: - if not all(k in submission for k in required_keys): - print("❌ Invalid submission format") + # Check all required keys are present and non-empty + for k in required_keys: + if k not in submission or not str(submission[k]).strip(): + print(f"❌ Invalid submission: missing or empty field '{k}'") + sys.exit(1) + # Check repository_url format + if not re.match(url_pattern, submission["repository_url"]): + print(f"❌ Invalid repository_url format: {submission['repository_url']}") sys.exit(1) print("✅ Valid submissions.json") except Exception as e: diff --git a/README.md b/README.md index 3bf9b55..d8092bf 100644 --- a/README.md +++ b/README.md @@ -65,9 +65,18 @@ This repository provides an **automated workflow** to manage **hackathon project --- +## ⚠️ Important Notes + +- **Deadline:** The current submission deadline is **June 30, 2025**. Update the deadline in `config.yml` at the root of the repository to change it. The workflow reads the deadline from this YAML config file. +- **Late Submissions:** PRs submitted after the deadline will be marked with `[LATE]` in the title and the `late-submission` label. Reviewers can still approve and merge late submissions, but they will be clearly marked. +- **Template Format:** The workflows require the issue template format to remain unchanged. If you modify the template, update the extraction logic in the workflow accordingly. +- **Repository Cloning:** Only public repositories under 100MB will be cloned. Private or oversized repositories will be skipped, and maintainers will be notified of any failures. + +--- + ## 🔧 Configuration -- **Add Labels:** Add labels `project-submission` and `late-submission` -- **Deadline Date:** Update the `DEADLINE` in `.github/workflows/submission-validation.yml` +- **Add Labels:** Add labels `project-submission` and `late-submission` to your repository. +- **Deadline Date:** Update the `deadline` in `config.yml` at the root of the repository. - **Required Fields in `submissions.json`**: ```json [ diff --git a/config.yml b/config.yml new file mode 100644 index 0000000..3842bfd --- /dev/null +++ b/config.yml @@ -0,0 +1 @@ +deadline: "2025-06-30T23:59:59Z"