diff --git a/.github/extendJSON/resolve.py b/.github/extendJSON/resolve.py index e985bf6b..0652deb2 100644 --- a/.github/extendJSON/resolve.py +++ b/.github/extendJSON/resolve.py @@ -1,5 +1,6 @@ import sys import json +import pydash from urllib.request import urlopen, Request def get_json_dict_from_url(url): @@ -28,6 +29,8 @@ def resolve_extended_json_file(file_data_dict): resolve = resolve_extended_json_file(superJsonDict) + pydash.merge(resolve, file_data_dict) + resolve['rules'].update(file_data_dict) resolve['rules'].pop('axioms') resolve['rules'].pop('$schema') diff --git a/.github/workflows/checklistMarkdownToPDF.yml b/.github/workflows/checklistMarkdownToPDF.yml new file mode 100644 index 00000000..5c34127b --- /dev/null +++ b/.github/workflows/checklistMarkdownToPDF.yml @@ -0,0 +1,68 @@ +name: Converting outbound checklists from .md to .pdf +on: + pull_request: + types: [opened, synchronize] + # Paths can be used to only trigger actions when you have edited checklist files + branches: + - 'checklists/**' + paths: + - 'tier*/checklist.md' + +jobs: + get-changed-directories: + name: Get changed directories + runs-on: ubuntu-latest + outputs: + tiers: ${{ steps.list-dirs.outputs.tiers }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 2 + - name: Get changed directories + id: get-dirs + uses: tj-actions/changed-files@v45 + with: + dir_names: "true" + - name: List all changed tier directories + id: list-dirs + env: + ALL_CHANGED_FILES: ${{ steps.get-dirs.outputs.all_changed_files }} + run: | + # Obtain changed tier directories and format into array + DIRS=$(echo "$ALL_CHANGED_FILES" | grep -oE 'tier[^ ]*' | sed 's/^/"/; s/$/"/' | paste -sd, -) + + # Output the array + TIER_DIRS="[$DIRS]" + echo "$TIER_DIRS" + + echo "tiers=$TIER_DIRS" >> "$GITHUB_OUTPUT" + + convert-to-pdf: + name: Build PDF + runs-on: ubuntu-latest + needs: get-changed-directories + permissions: + contents: write + strategy: + max-parallel: 1 + matrix: + tier: ${{ fromJSON(needs.get-changed-directories.outputs.tiers) }} # List of changed tier directories + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref }} + - name: Generate PDF for ${{ matrix.tier }} + uses: baileyjm02/markdown-to-pdf@v1 + with: + input_path: ${{ matrix.tier }}/checklist.md + images_dir: assets + image_import: ../assets + output_dir: ${{ matrix.tier }}/ + build_html: false + - name: Commit and push ${{ matrix.tier }} PDF + uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: "Updated ${{ matrix.tier }} checklist pdf" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index f9103cae..287dbf7e 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -49,6 +49,8 @@ jobs: # # Default: "[Repolinter] Open Source Policy Issues" output_name: '[Repolinter] Tier 3 Repository Hygiene Issue' + label_name: 'Tier 3 Remediation' + label_color: 'ff69b4' # The default token is the repolinter token for the DSACMS org # You can change it if needed. diff --git a/maturity-model-tiers.md b/maturity-model-tiers.md index e0f436e8..32052029 100644 --- a/maturity-model-tiers.md +++ b/maturity-model-tiers.md @@ -60,7 +60,7 @@ This document outlines the maturity model tiers. | File | Tier 0 | Tier 1 | Tier 2 | Tier 3 | Tier 4 | |--------------------------|--------|--------|--------|--------|--------| | LICENSE | $\color{green}\large{\textsf{M}}$ | $\color{green}\large{\textsf{M}}$ | $\color{green}\large{\textsf{M}}$ | $\color{green}\large{\textsf{M}}$ | $\color{green}\large{\textsf{M}}$ | -| SECURITY.md | $\color{lightcoral}\large{\textsf{N}}$ | $\color{green}\large{\textsf{M}}$ | $\color{green}\large{\textsf{M}}$ | $\color{green}\large{\textsf{M}}$ | $\color{green}\large{\textsf{M}}$ | +| SECURITY.md | $\color{blue}\large{\textsf{R}}$ | $\color{green}\large{\textsf{M}}$ | $\color{green}\large{\textsf{M}}$ | $\color{green}\large{\textsf{M}}$ | $\color{green}\large{\textsf{M}}$ | | README.md | $\color{green}\large{\textsf{M}}$ | $\color{green}\large{\textsf{M}}$ | $\color{green}\large{\textsf{M}}$ | $\color{green}\large{\textsf{M}}$ | $\color{green}\large{\textsf{M}}$ | | CONTRIBUTING.md | $\color{blue}\large{\textsf{R}}$ | $\color{blue}\large{\textsf{R}}$ | $\color{green}\large{\textsf{M}}$ | $\color{green}\large{\textsf{M}}$ | $\color{green}\large{\textsf{M}}$ | | MAINTAINERS.md | $\color{lightcoral}\large{\textsf{N}}$ | $\color{lightcoral}\large{\textsf{N}}$ | $\color{blue}\large{\textsf{R}}$ | $\color{green}\large{\textsf{M}}$ | $\color{green}\large{\textsf{M}}$ | @@ -98,7 +98,7 @@ This document outlines the maturity model tiers. SECURITY.md Security & Responsible Disclosure Policy - $\color{lightcoral}\large{\textsf{N}}$ + $\color{blue}\large{\textsf{R}}$ $\color{green}\large{\textsf{M}}$ $\color{green}\large{\textsf{M}}$ $\color{green}\large{\textsf{M}}$ diff --git a/maturity-model-tiers.pdf b/maturity-model-tiers.pdf index 9d1223be..8ac2d107 100644 Binary files a/maturity-model-tiers.pdf and b/maturity-model-tiers.pdf differ diff --git a/requirements.txt b/requirements.txt index 7de92283..f5cfbb1f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -cookiecutter==2.4.0 +cookiecutter==2.6.0 diff --git a/tier0/README.md b/tier0/README.md new file mode 100644 index 00000000..62f4d341 --- /dev/null +++ b/tier0/README.md @@ -0,0 +1,26 @@ +# Tier 0: Private Repository + +## What is a Tier 0 Project? + +A **Tier 0** project is an **experimental or historical** repository that is **private** and generally used by a single developer or a small group. It typically includes working projects, example scripts, or early prototypes that serve as a foundation for future work or experimentation. This type of project is not shared publicly and often remains private due to its preliminary or incomplete nature. + +The main purpose of a Tier 0 project is to provide a space for initial development, exploration, and testing. These repositories generally lack formal documentation or governance structures that are typical of more mature projects. + +### Key Characteristics of a Tier 0 Project: +- **Private** and often limited to individual or small team access. +- Primarily **experimental or developmental** in nature. + +--- + +## Files for a Tier 0 Project + +Although these projects are private, there are specific files that are required and recommended to include in the repository as part of the CMS Open Source Program Office's repository hygiene guidelines and standards. + +| **File** | **Requirement** | **Description** | +|-----------------------|-----------------|-------------------------------------------------------------------------------------------------------------| +| `LICENSE` | Mandatory | Defines the licensing terms under which the project is distributed. | +| `SECURITY.md` | Recommended | Outlines the agency's security policies, including how to report security issues or vulnerabilities in the code. | +| `README.md` | Mandatory | Provides an overview of the project, including its purpose, setup instructions, or any relevant notes for the developer(s). | +| `CONTRIBUTING.md` | Recommended | Guidelines for contributing, useful if the project is later opened to collaborators or transitioned to a public repository. | + +For more information about sections and content within the files above, please visit [maturity-model-tiers.md](https://github.com/DSACMS/repo-scaffolder/blob/main/maturity-model-tiers.md). \ No newline at end of file diff --git a/tier0/{{cookiecutter.project_slug}}/README.md b/tier0/{{cookiecutter.project_slug}}/README.md index c10caac1..394c673d 100644 --- a/tier0/{{cookiecutter.project_slug}}/README.md +++ b/tier0/{{cookiecutter.project_slug}}/README.md @@ -20,9 +20,9 @@ TODO: Recommended to include since this is an agency-led project --> ### Team Mission TODO: Recommended to include since this is an agency-led project --> -## Author / Team + -## Running Locally + ## Core Team -A full list of contributors can be found on [https://github.cms.gov/{{ cookiecutter.project_org }}/{{ cookiecutter.project_repo_name }}/graphs/contributors](https://github.cms.gov/{{ cookiecutter.project_org }}/{{ cookiecutter.project_repo_name }}/graphs/contributors). +A full list of contributors can be found on [https://github.com/{{ cookiecutter.project_org }}/{{ cookiecutter.project_repo_name }}/graphs/contributors](https://github.com/{{ cookiecutter.project_org }}/{{ cookiecutter.project_repo_name }}/graphs/contributors). ).*?()/$1 '"$CONTRIBUTORS"' $2/' MAINTAINERS.md - - name: Get repository contributors count - id: get_contributors - # https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#list-repository-contributors - # https://docs.github.com/en/graphql/reference/objects#repositorycollaboratorconnection - # https://docs.github.com/en/graphql/guides/forming-calls-with-graphql#communicating-with-graphql - # CANNOT have newlines! - run: | - {% raw %} - OWNER=$(echo $GITHUB_REPOSITORY | cut -d'/' -f1) - REPO=$(echo $GITHUB_REPOSITORY | cut -d'/' -f2) - QUERY='query { repository(owner: \"'"$OWNER"'\", name: \"'"$REPO"'\") { collaborators { totalCount } } }' - CONTRIBUTORS=$(curl -s -X POST -H "Authorization: bearer ${{ secrets.GITHUB_TOKEN }}" -H "Content-Type: application/json" -d "{\"query\": \"$QUERY\"}" https://api.github.com/graphql | jq -r '.data.repository.collaborators.totalCount') - echo "Total contributors: $CONTRIBUTORS" - echo "contributors=$CONTRIBUTORS" >> $GITHUB_OUTPUT - {% endraw %} + git config user.name 'github-actions[bot]' + git config user.email 'github-actions[bot]@users.noreply.github.com' + git add MAINTAINERS.md + git commit -m "update contributors count to $CONTRIBUTORS" || exit 0 - - name: Replace slug in MAINTAINERS.md with number of contributors - # https://stackoverflow.com/questions/10613643/replace-a-unknown-string-between-two-known-strings-with-sed - run: | - {% raw %} - CONTRIBUTORS=${{ steps.get_contributors.outputs.contributors }} - sed -i 's/.*/ '"$CONTRIBUTORS"' /g' MAINTAINERS.md - {% endraw %} + - name: Push protected + uses: CasperWA/push-protected@v2 + with: + {% raw %} + token: ${{ secrets.PUSH_TO_PROTECTED_BRANCH }} + {% endraw %} - - name: Commit and push changes - # https://github.com/orgs/community/discussions/26560#discussioncomment-3531273 - # commit changes, but if no changes exist, then exit cleanly - run: | - git config user.name 'github-actions[bot]' - git config user.email 'github-actions[bot]@users.noreply.github.com' - git add MAINTAINERS.md - git commit -m "BOT: Update contributors info in MAINTAINERS.md" || exit 0 - git push + branch: main \ No newline at end of file diff --git a/tier2/{{cookiecutter.project_slug}}/MAINTAINERS.md b/tier2/{{cookiecutter.project_slug}}/MAINTAINERS.md index 4d8d9291..9944778b 100644 --- a/tier2/{{cookiecutter.project_slug}}/MAINTAINERS.md +++ b/tier2/{{cookiecutter.project_slug}}/MAINTAINERS.md @@ -11,6 +11,8 @@ This is a list of maintainers for this project. See [CODEOWNERS.md](./CODEOWNERS ## Contributors + + Total number of contributors: @@ -31,11 +33,21 @@ Total number of contributors: -* [Preparing a Release Candidate](#preparing-a-release-candidate) - * [Incorporating feedback from review](#incorporating-feedback-from-review) -* [Making a Release](#making-a-release) -* [Auto Changelog](#auto-changelog) -* [Hotfix Releases](#hotfix-releases) +- [Maintainers](#maintainers) + - [Maintainers:](#maintainers-1) + - [Contributors](#contributors) +- [Tier 2 Release Guidelines](#tier-2-release-guidelines) + - [Table of Contents](#table-of-contents) + - [Versioning](#versioning) + - [Release Process](#release-process) + - [Goals](#goals) + - [Schedule](#schedule) + - [Communication and Workflow](#communication-and-workflow) + - [Preparing a Release Candidate](#preparing-a-release-candidate) + - [Incorporating feedback from review](#incorporating-feedback-from-review) + - [Making a Release](#making-a-release) + - [Auto Changelog](#auto-changelog) + - [Hotfix Releases](#hotfix-releases) ## Versioning diff --git a/tier3/checklist.md b/tier3/checklist.md index d058df94..dcf3b6bb 100644 --- a/tier3/checklist.md +++ b/tier3/checklist.md @@ -35,7 +35,6 @@ If you would like your repository to be released, please complete the following [Flipping the Switch: Making the Repository Public](#flipping-the-switch-making-the-repository-public) - ### State the Benefits of Open Sourcing the Project - [ ] **Cost Savings** diff --git a/tier3/checklist.pdf b/tier3/checklist.pdf index ad44d4f5..284c1986 100644 Binary files a/tier3/checklist.pdf and b/tier3/checklist.pdf differ diff --git a/tier3/{{cookiecutter.project_slug}}/.github/codejson/hooks/post_gen_project.py b/tier3/{{cookiecutter.project_slug}}/.github/codejson/hooks/post_gen_project.py index aa143013..211c1a02 100644 --- a/tier3/{{cookiecutter.project_slug}}/.github/codejson/hooks/post_gen_project.py +++ b/tier3/{{cookiecutter.project_slug}}/.github/codejson/hooks/post_gen_project.py @@ -23,7 +23,16 @@ def get_scc_labor_hours(): try: #Run scc and load results into a dictionary #assuming we are in the .git directory of the repo - d = json.loads(subprocess.run(["scc","..", "--format","json2"],check=True, capture_output=True).stdout) + cmd = ['scc', '..', '--format', 'json2', '--exclude-file'] + + # Currently only supports specific files + files_to_exclude = [ + "checks.yml,auto-changelog.yml,contributors.yml,repoStructure.yml,code.json,checklist.md,checklist.pdf,README.md,CONTIRBUTING.md,LICENSE,MAINTAINERS.md,repolinter.json,SECURITY.md,CODE_OF_CONDUCT.md,CODEOWNERS.md,COMMUNITY_GUIDELINES.md,GOVERANCE.md" + ] + + cmd.extend(files_to_exclude) + + d = json.loads(subprocess.run(cmd,check=True, capture_output=True).stdout) l_hours = d['estimatedScheduleMonths'] * 730.001 @@ -42,6 +51,13 @@ def prompt_exemption_text(exemptionType): print(f"You have selected {exemptionType} for your Usage Type.") return input("Please provide a one or two sentence justification for the exemption used: ") +def format_multi_select_fields(text): + new_text = text.split(",") + + new_text = [text.strip() for text in new_text] + + return new_text + def update_code_json(json_file_path): # Read the JSON with open(json_file_path, 'r') as file: @@ -50,18 +66,25 @@ def update_code_json(json_file_path): # Add date_information and labor hours to the JSON data['date'] = get_date_fields() + # Calculate labor hours hours = get_scc_labor_hours() if hours: data['laborHours'] = hours else: data['laborHours'] = None + # Check if usageType is an exemption if data['permissions']['usageType'].startswith('exempt'): exemption_text = prompt_exemption_text(data['permissions']['usageType']) data['permissions']['exemptionText'] = exemption_text else: del data['permissions']['exemptionText'] + # Format multi-select options + data['categories'] = format_multi_select_fields(data['categories'][0]) + data['languages'] = format_multi_select_fields(data['languages'][0]) + data['tags'] = format_multi_select_fields(data['tags'][0]) + # Update the JSON with open(json_file_path, 'w') as file: json.dump(data, file, indent = 2) diff --git a/tier3/{{cookiecutter.project_slug}}/.github/workflows/contributors.yml b/tier3/{{cookiecutter.project_slug}}/.github/workflows/contributors.yml index 3ab38c54..80d45eba 100644 --- a/tier3/{{cookiecutter.project_slug}}/.github/workflows/contributors.yml +++ b/tier3/{{cookiecutter.project_slug}}/.github/workflows/contributors.yml @@ -1,68 +1,78 @@ +name: Update Contributors Information + on: - push: - branches: - - main - workflow_dispatch: + workflow_dispatch: {} + schedule: + # Weekly on Saturdays. + - cron: "30 1 * * 6" + push: + branches: [main] jobs: - update-contributors: - runs-on: ubuntu-latest - name: Update contributors info in MAINTAINERS.md - permissions: - contents: write - pull-requests: write - steps: - # Update contributor list - - name: Contribute List - uses: akhilmhdh/contributors-readme-action@v2.3.10 - env: - {% raw %} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - {% endraw %} - with: - # https://github.com/marketplace/actions/contribute-list#optional-parameters - readme_path: MAINTAINERS.md - use_username: false - commit_message: "BOT: Update contributors info in MAINTAINERS.md" + update-contributors: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Update contributor list + id: contrib_list + uses: akhilmhdh/contributors-readme-action@v2.3.10 + env: + {% raw %} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + {% endraw %} + with: + readme_path: MAINTAINERS.md + use_username: false + commit_message: "update contributors information" + + - name: Get contributors count + id: get_contributors + env: + {% raw %} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + {% endraw %} + + run: | + OWNER=$(echo $GITHUB_REPOSITORY | cut -d'/' -f1) + REPO=$(echo $GITHUB_REPOSITORY | cut -d'/' -f2) + QUERY='query { repository(owner: \"'"$OWNER"'\", name: \"'"$REPO"'\") { collaborators { totalCount } } }' + + CONTRIBUTORS=$(gh api \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "/repos/$OWNER/$REPO/contributors?per_page=100" | \ + jq '[.[] | select(.type != "Bot" and (.login | test("\\[bot\\]$") | not) and (.login | test("-bot$") | not))] | length') + + echo "Total contributors: $CONTRIBUTORS" + echo "contributors=$CONTRIBUTORS" >> $GITHUB_OUTPUT + - # Update contributor count - - name: Checkout repository - uses: actions/checkout@v4 + - name: Update MAINTAINERS.md + run: | + {% raw %} + CONTRIBUTORS="${{ steps.get_contributors.outputs.contributors }}" + {% endraw %} - - name: Pull changes from contributors-readme-action - run: | - git pull + perl -i -pe 's/().*?()/$1 '"$CONTRIBUTORS"' $2/' MAINTAINERS.md - - name: Get repository contributors count - id: get_contributors - # https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#list-repository-contributors - # https://docs.github.com/en/graphql/reference/objects#repositorycollaboratorconnection - # https://docs.github.com/en/graphql/guides/forming-calls-with-graphql#communicating-with-graphql - # CANNOT have newlines! - run: | - {% raw %} - OWNER=$(echo $GITHUB_REPOSITORY | cut -d'/' -f1) - REPO=$(echo $GITHUB_REPOSITORY | cut -d'/' -f2) - QUERY='query { repository(owner: \"'"$OWNER"'\", name: \"'"$REPO"'\") { collaborators { totalCount } } }' - CONTRIBUTORS=$(curl -s -X POST -H "Authorization: bearer ${{ secrets.GITHUB_TOKEN }}" -H "Content-Type: application/json" -d "{\"query\": \"$QUERY\"}" https://api.github.com/graphql | jq -r '.data.repository.collaborators.totalCount') - echo "Total contributors: $CONTRIBUTORS" - echo "contributors=$CONTRIBUTORS" >> $GITHUB_OUTPUT - {% endraw %} + git config user.name 'github-actions[bot]' + git config user.email 'github-actions[bot]@users.noreply.github.com' + git add MAINTAINERS.md + git commit -m "update contributors count to $CONTRIBUTORS" || exit 0 - - name: Replace slug in MAINTAINERS.md with number of contributors - # https://stackoverflow.com/questions/10613643/replace-a-unknown-string-between-two-known-strings-with-sed - run: | - {% raw %} - CONTRIBUTORS=${{ steps.get_contributors.outputs.contributors }} - sed -i 's/.*/ '"$CONTRIBUTORS"' /g' MAINTAINERS.md - {% endraw %} + - name: Push protected + uses: CasperWA/push-protected@v2 + with: + {% raw %} + token: ${{ secrets.PUSH_TO_PROTECTED_BRANCH }} + {% endraw %} - - name: Commit and push changes - # https://github.com/orgs/community/discussions/26560#discussioncomment-3531273 - # commit changes, but if no changes exist, then exit cleanly - run: | - git config user.name 'github-actions[bot]' - git config user.email 'github-actions[bot]@users.noreply.github.com' - git add MAINTAINERS.md - git commit -m "BOT: Update contributors info in MAINTAINERS.md" || exit 0 - git push + branch: main \ No newline at end of file diff --git a/tier3/{{cookiecutter.project_slug}}/MAINTAINERS.md b/tier3/{{cookiecutter.project_slug}}/MAINTAINERS.md index 38196d45..c4b3ec45 100644 --- a/tier3/{{cookiecutter.project_slug}}/MAINTAINERS.md +++ b/tier3/{{cookiecutter.project_slug}}/MAINTAINERS.md @@ -21,6 +21,8 @@ This is a list of maintainers for this project. See [CODEOWNERS.md](./CODEOWNERS ## Contributors + + Total number of contributors: diff --git a/tier4/checklist.md b/tier4/checklist.md index 25a6929d..af3590ae 100644 --- a/tier4/checklist.md +++ b/tier4/checklist.md @@ -36,7 +36,6 @@ If you would like your repository to be released, please complete the following [Flipping the Switch: Making the Repository Public](#flipping-the-switch-making-the-repository-public) - ### State the Benefits of Open Sourcing the Project - [ ] **Cost Savings** diff --git a/tier4/checklist.pdf b/tier4/checklist.pdf index 4597099f..42d92fb0 100644 Binary files a/tier4/checklist.pdf and b/tier4/checklist.pdf differ diff --git a/tier4/{{cookiecutter.project_slug}}/.github/codejson/hooks/post_gen_project.py b/tier4/{{cookiecutter.project_slug}}/.github/codejson/hooks/post_gen_project.py index 9c8f6122..7c525ced 100644 --- a/tier4/{{cookiecutter.project_slug}}/.github/codejson/hooks/post_gen_project.py +++ b/tier4/{{cookiecutter.project_slug}}/.github/codejson/hooks/post_gen_project.py @@ -23,8 +23,17 @@ def get_scc_labor_hours(): try: #Run scc and load results into a dictionary #assuming we are in the .git directory of the repo - d = json.loads(subprocess.run(["scc","..", "--format","json2"],check=True, capture_output=True).stdout) - + cmd = ['scc', '..', '--format', 'json2', '--exclude-file'] + + # Currently only supports specific files + files_to_exclude = [ + "checks.yml,auto-changelog.yml,contributors.yml,repoStructure.yml,code.json,checklist.md,checklist.pdf,README.md,CONTIRBUTING.md,LICENSE,MAINTAINERS.md,repolinter.json,SECURITY.md,CODE_OF_CONDUCT.md,CODEOWNERS.md,COMMUNITY_GUIDELINES.md,GOVERANCE.md" + ] + + cmd.extend(files_to_exclude) + + d = json.loads(subprocess.run(cmd,check=True, capture_output=True).stdout) + l_hours = d['estimatedScheduleMonths'] * 730.001 return round(l_hours,2) @@ -37,11 +46,18 @@ def get_scc_labor_hours(): #Otherwise just use previous value as a default value. return None - + def prompt_exemption_text(exemptionType): print(f"You have selected {exemptionType} for your Usage Type.") return input("Please provide a one or two sentence justification for the exemption used: ") +def format_multi_select_fields(text): + new_text = text.split(",") + + new_text = [text.strip() for text in new_text] + + return new_text + def update_code_json(json_file_path): # Read the JSON with open(json_file_path, 'r') as file: @@ -50,18 +66,25 @@ def update_code_json(json_file_path): # Add date_information and labor hours to the JSON data['date'] = get_date_fields() + # Calculate labor hours hours = get_scc_labor_hours() if hours: data['laborHours'] = hours else: data['laborHours'] = None + # Check if usageType is an exemption if data['permissions']['usageType'].startswith('exempt'): exemption_text = prompt_exemption_text(data['permissions']['usageType']) data['permissions']['exemptionText'] = exemption_text else: del data['permissions']['exemptionText'] + # Format multi-select options + data['categories'] = format_multi_select_fields(data['categories'][0]) + data['languages'] = format_multi_select_fields(data['languages'][0]) + data['tags'] = format_multi_select_fields(data['tags'][0]) + # Update the JSON with open(json_file_path, 'w') as file: json.dump(data, file, indent = 2) diff --git a/tier4/{{cookiecutter.project_slug}}/.github/workflows/contributors.yml b/tier4/{{cookiecutter.project_slug}}/.github/workflows/contributors.yml index 3ab38c54..80d45eba 100644 --- a/tier4/{{cookiecutter.project_slug}}/.github/workflows/contributors.yml +++ b/tier4/{{cookiecutter.project_slug}}/.github/workflows/contributors.yml @@ -1,68 +1,78 @@ +name: Update Contributors Information + on: - push: - branches: - - main - workflow_dispatch: + workflow_dispatch: {} + schedule: + # Weekly on Saturdays. + - cron: "30 1 * * 6" + push: + branches: [main] jobs: - update-contributors: - runs-on: ubuntu-latest - name: Update contributors info in MAINTAINERS.md - permissions: - contents: write - pull-requests: write - steps: - # Update contributor list - - name: Contribute List - uses: akhilmhdh/contributors-readme-action@v2.3.10 - env: - {% raw %} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - {% endraw %} - with: - # https://github.com/marketplace/actions/contribute-list#optional-parameters - readme_path: MAINTAINERS.md - use_username: false - commit_message: "BOT: Update contributors info in MAINTAINERS.md" + update-contributors: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Update contributor list + id: contrib_list + uses: akhilmhdh/contributors-readme-action@v2.3.10 + env: + {% raw %} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + {% endraw %} + with: + readme_path: MAINTAINERS.md + use_username: false + commit_message: "update contributors information" + + - name: Get contributors count + id: get_contributors + env: + {% raw %} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + {% endraw %} + + run: | + OWNER=$(echo $GITHUB_REPOSITORY | cut -d'/' -f1) + REPO=$(echo $GITHUB_REPOSITORY | cut -d'/' -f2) + QUERY='query { repository(owner: \"'"$OWNER"'\", name: \"'"$REPO"'\") { collaborators { totalCount } } }' + + CONTRIBUTORS=$(gh api \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "/repos/$OWNER/$REPO/contributors?per_page=100" | \ + jq '[.[] | select(.type != "Bot" and (.login | test("\\[bot\\]$") | not) and (.login | test("-bot$") | not))] | length') + + echo "Total contributors: $CONTRIBUTORS" + echo "contributors=$CONTRIBUTORS" >> $GITHUB_OUTPUT + - # Update contributor count - - name: Checkout repository - uses: actions/checkout@v4 + - name: Update MAINTAINERS.md + run: | + {% raw %} + CONTRIBUTORS="${{ steps.get_contributors.outputs.contributors }}" + {% endraw %} - - name: Pull changes from contributors-readme-action - run: | - git pull + perl -i -pe 's/().*?()/$1 '"$CONTRIBUTORS"' $2/' MAINTAINERS.md - - name: Get repository contributors count - id: get_contributors - # https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#list-repository-contributors - # https://docs.github.com/en/graphql/reference/objects#repositorycollaboratorconnection - # https://docs.github.com/en/graphql/guides/forming-calls-with-graphql#communicating-with-graphql - # CANNOT have newlines! - run: | - {% raw %} - OWNER=$(echo $GITHUB_REPOSITORY | cut -d'/' -f1) - REPO=$(echo $GITHUB_REPOSITORY | cut -d'/' -f2) - QUERY='query { repository(owner: \"'"$OWNER"'\", name: \"'"$REPO"'\") { collaborators { totalCount } } }' - CONTRIBUTORS=$(curl -s -X POST -H "Authorization: bearer ${{ secrets.GITHUB_TOKEN }}" -H "Content-Type: application/json" -d "{\"query\": \"$QUERY\"}" https://api.github.com/graphql | jq -r '.data.repository.collaborators.totalCount') - echo "Total contributors: $CONTRIBUTORS" - echo "contributors=$CONTRIBUTORS" >> $GITHUB_OUTPUT - {% endraw %} + git config user.name 'github-actions[bot]' + git config user.email 'github-actions[bot]@users.noreply.github.com' + git add MAINTAINERS.md + git commit -m "update contributors count to $CONTRIBUTORS" || exit 0 - - name: Replace slug in MAINTAINERS.md with number of contributors - # https://stackoverflow.com/questions/10613643/replace-a-unknown-string-between-two-known-strings-with-sed - run: | - {% raw %} - CONTRIBUTORS=${{ steps.get_contributors.outputs.contributors }} - sed -i 's/.*/ '"$CONTRIBUTORS"' /g' MAINTAINERS.md - {% endraw %} + - name: Push protected + uses: CasperWA/push-protected@v2 + with: + {% raw %} + token: ${{ secrets.PUSH_TO_PROTECTED_BRANCH }} + {% endraw %} - - name: Commit and push changes - # https://github.com/orgs/community/discussions/26560#discussioncomment-3531273 - # commit changes, but if no changes exist, then exit cleanly - run: | - git config user.name 'github-actions[bot]' - git config user.email 'github-actions[bot]@users.noreply.github.com' - git add MAINTAINERS.md - git commit -m "BOT: Update contributors info in MAINTAINERS.md" || exit 0 - git push + branch: main \ No newline at end of file diff --git a/tier4/{{cookiecutter.project_slug}}/MAINTAINERS.md b/tier4/{{cookiecutter.project_slug}}/MAINTAINERS.md index b600b9f2..4dc165ee 100644 --- a/tier4/{{cookiecutter.project_slug}}/MAINTAINERS.md +++ b/tier4/{{cookiecutter.project_slug}}/MAINTAINERS.md @@ -21,6 +21,8 @@ This is a list of maintainers for this project. See [CODEOWNERS.md](./CODEOWNERS ## Contributors + + Total number of contributors: @@ -33,13 +35,25 @@ Total number of contributors: * [Preparing a Release Candidate](#preparing-a-release-candidate) * [Incorporating feedback from review](#incorporating-feedback-from-review)