diff --git a/.github/ISSUE_TEMPLATE/new_submission.yml b/.github/ISSUE_TEMPLATE/new_submission.yml new file mode 100644 index 0000000..f118ead --- /dev/null +++ b/.github/ISSUE_TEMPLATE/new_submission.yml @@ -0,0 +1,51 @@ +name: Submission Form +description: Submit a new Frappe App or Resource to the Awesome Frappe list +title: "[Submission] - " +labels: ["new-submission"] +body: + - type: dropdown + id: category + attributes: + label: Category + multiple: false + options: + - Apps + - Developer Tooling + - Other Tooling + - Deployment Tools + - Resources + - Hosting + validations: + required: true + - type: dropdown + id: sub_category + attributes: + label: Sub Category + options: + # Apps + - Business Apps + - Utility Apps + - Plugins + - Integrations + - Themes + - Regional Apps + - Other Apps + # Developer Tooling + - SDKs & Libraries + - Templates + - type: input + attributes: + label: App or Resource URL + validations: + required: true + - type: input + attributes: + label: App or Resource Name + validations: + required: true + - type: textarea + attributes: + label: App or Resource Description + placeholder: A short description of the app or resource + validations: + required: true diff --git a/.github/helper/approval.py b/.github/helper/approval.py new file mode 100644 index 0000000..e967aa0 --- /dev/null +++ b/.github/helper/approval.py @@ -0,0 +1,29 @@ +import sys +import os +import requests + +ISSUE_NUMBER = os.environ.get("ISSUE_NUMBER") # "1200" +GITHUB_REPOSITORY = os.environ.get("GITHUB_REPOSITORY") # "octocat/Hello-World" +GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN") # "1234567890" + +if __name__ == "__main__": + ENDPOINT_URL = f"https://api.github.com/repos/{GITHUB_REPOSITORY}/issues/{ISSUE_NUMBER}/comments" + COLLABORATOR_URL = f"https://api.github.com/repos/{GITHUB_REPOSITORY}/collaborators/{{username}}" + ISSUE_COMMENTS = requests.get(ENDPOINT_URL).json() + + for comment in ISSUE_COMMENTS: + username = comment["user"]["login"] + comment_body = comment["body"] + + if "LGTM" not in comment_body: + continue + print(f"LGTM found by {username}") + + is_collaborator = requests.get(COLLABORATOR_URL.format(username=username), headers={"Authorization": f"token {GITHUB_TOKEN}"}).ok + + if is_collaborator: + print(f"{username} is a collaborator and issue is approved") + sys.exit(0) # exit with success code if a collaborator has dropped a LGTM comment + + print("No one has dropped a LGTM comment") + sys.exit(1) # exit with error code if no collaborator has approved the affirmation diff --git a/.github/record_sorter.py b/.github/helper/record_sorter.py similarity index 100% rename from .github/record_sorter.py rename to .github/helper/record_sorter.py diff --git a/.github/helper/update.py b/.github/helper/update.py new file mode 100644 index 0000000..0477635 --- /dev/null +++ b/.github/helper/update.py @@ -0,0 +1,26 @@ +import os +import json + + +if __name__ == "__main__": + WORKSPACE = os.environ.get("GITHUB_WORKSPACE") + AWESOME_FILE = f"{WORKSPACE}/README.md" + + FILE_ENTRIES_BY_LINE = open(AWESOME_FILE).readlines() + USER_SUBMISSION: dict = json.loads(os.environ.get("submission_entry") or"{}") + + # add user submission to affirmations file + category_index = FILE_ENTRIES_BY_LINE.index(f"### {USER_SUBMISSION['category']}\n") + insert_at_index = category_index + 1 + + if sub_category := USER_SUBMISSION['sub_category']: + sub_category_index = FILE_ENTRIES_BY_LINE.index(f"#### {USER_SUBMISSION['sub_category']}\n", category_index) + insert_at_index = sub_category_index + 1 + + FILE_ENTRIES_BY_LINE.insert(insert_at_index, f"- [{USER_SUBMISSION['app_or_resource_name']}]({USER_SUBMISSION['app_or_resource_url']}) - {USER_SUBMISSION['app_or_resource_description']}\n") + + # update affirmations file + with open(AWESOME_FILE, "w") as f: + f.write(FILE_ENTRIES_BY_LINE) + + print(f"Updated {AWESOME_FILE} with {USER_SUBMISSION}") diff --git a/.github/workflows/contribute.yml b/.github/workflows/contribute.yml new file mode 100644 index 0000000..350b455 --- /dev/null +++ b/.github/workflows/contribute.yml @@ -0,0 +1,64 @@ +name: Submissions via Issues +on: + issue_comment: + types: [created, edited] + +jobs: + approval: + # this job only runs for issue comments + name: Check if submission is approved + runs-on: ubuntu-latest + if: ${{ github.event.issue.number }} + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.PAT }} + - uses: actions/setup-python@v5 + with: + python-version: '3.13' + - name: Check if authorized member has approved submission + run: | + pip install requests + python ${GITHUB_WORKSPACE}/.github/helper/approval.py + env: + ISSUE_NUMBER: ${{ github.event.issue.number }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + contribution: + name: Extract, Commit & Push submission to default branch + runs-on: ubuntu-latest + needs: approval + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.13' + + - uses: stefanbuck/github-issue-parser@v3 + id: issue-parser + with: + template-path: ${GITHUB_WORKSPACE}/.github/ISSUE_TEMPLATE/new_submission.yml + + - name: Update submissions file + run: python ${GITHUB_WORKSPACE}/.github/helper/update.py + env: + submission_entry: ${{ steps.issue-parser.outputs.jsonString }} + + - name: Record Sorter + run: python ${GITHUB_WORKSPACE}/.github/helper/record_sorter.py + + - name: Commit + Push changes + uses: EndBug/add-and-commit@v9 + with: + message: 'docs: New Submission via Issue' + + cleanup: + name: Close Issue thread after successful contribution + runs-on: ubuntu-latest + needs: contribution + steps: + - name: Close Issue + uses: peter-evans/close-issue@v3 + with: + issue-number: ${{ github.event.issue.number }} + comment: Auto-closing issue since commit has been pushed to main branch diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bf16dfb..6652f75 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,6 +14,6 @@ repos: hooks: - id: records-sorter name: Sort README - entry: python .github/record_sorter.py + entry: python .github/helper/record_sorter.py language: system types: [markdown]