From 4fcc224c42deb6cebecf2eaf5a155dc1d164ba45 Mon Sep 17 00:00:00 2001 From: Herbert Damker Date: Tue, 15 Apr 2025 15:42:06 +0200 Subject: [PATCH 1/3] Update of automation workflow setup-new-repo, templates and documentation (#21) * Update README.md * Update README.md * Update initial-admin.md * Update setup-new-repo.yml adding cleanup step * Update setup-new-repo.yml * Update setup-new-repo.yml * Update setup-new-repo.yml * Update setup-new-repo.yml * Update setup-new-repo.yml * Update setup-new-repo.yml * Update setup-new-repo.yml * Update setup-new-repo.yml * Update setup-new-repo.yml * Refactored clean up step * Update prerrequisites * Renamed CODEOWNERS_TEMPLATE * More detailed repository description * Added comments within the workflow * Updated workflow documentation * Some more comments and improvements of the workflow * Revert change of token check * Update documentation regarding token creation --- .github/workflows/setup-new-repo.yml | 86 +++++++-- CODEOWNERS | 4 +- README.md | 27 +-- templates/{CODEOWNERS => CODEOWNERS_TEMPLATE} | 0 templates/README.md | 166 ++++++++++-------- templates/issues/initial-admin.md | 4 +- 6 files changed, 191 insertions(+), 96 deletions(-) rename templates/{CODEOWNERS => CODEOWNERS_TEMPLATE} (100%) diff --git a/.github/workflows/setup-new-repo.yml b/.github/workflows/setup-new-repo.yml index 45856dd..4266942 100644 --- a/.github/workflows/setup-new-repo.yml +++ b/.github/workflows/setup-new-repo.yml @@ -1,4 +1,18 @@ # .github/workflows/setup-new-repo.yml +# +# Prerequisites: +# - A GitHub environment named `repo-setup` must exist. +# - The environment must contain a secret `GH_REPO_CREATE_TOKEN`. +# - This token must be a fine-grained personal access token (FGPAT) with the following: +# β€’ Repository access: Allow access to the template repo and target org repos. +# β€’ Permissions: +# - Contents: Read and write +# - Issues: Read and write +# - Metadata: Read-only +# - Administration: Read and write (for repo settings, team setup) +# +# See: https://github.com/settings/tokens for generating tokens +# name: Setup New Repository on: @@ -38,24 +52,39 @@ jobs: - name: Checkout template repository uses: actions/checkout@v4 - - name: Set up GitHub CLI token with personal access token + - name: Set up GitHub CLI token with personal fine grained access token run: | + # Use GH_REPO_CREATE_TOKEN as the authentication token for all GitHub CLI commands echo "GH_TOKEN=${{ secrets.GH_REPO_CREATE_TOKEN }}" >> $GITHUB_ENV - echo "Token GH_REPO_CREATE_TOKEN ready for use in GitHub CLI" + if [ -z "${{ secrets.GH_REPO_CREATE_TOKEN }}" ]; then + echo "::error::GH_REPO_CREATE_TOKEN is not set. Please configure the secret in the 'repo-setup' environment." + exit 1 + fi - name: Create new repository and set variables run: | REPO_NAME=${{ github.event.inputs.repo_name }} + # Extract the owner (user or organization) part of the current repository (before the slash) OWNER=$(echo '${{ github.repository }}' | cut -d'/' -f1) - echo "Checking if repository $OWNER/$REPO_NAME already exists..." - if gh api repos/$OWNER/$REPO_NAME > /dev/null 2>&1; then - echo "::error::Repository $OWNER/$REPO_NAME already exists. Exiting." - exit 1 - fi - echo "Creating new repository: https://github.com/$OWNER/$REPO_NAME" - gh repo create "$OWNER/$REPO_NAME" --public --template "$OWNER/$(basename '${{ github.repository }}')" --confirm + # Creates a new public repository using the current repository as a template + gh repo create "$OWNER/$REPO_NAME" --public --template "$OWNER/$(basename '${{ github.repository }}')" + + # Wait until the repository is fully accessible + for i in {1..5}; do + if gh api repos/$OWNER/$REPO_NAME > /dev/null 2>&1; then + echo "::notice::Repository $OWNER/$REPO_NAME is now available." + break + else + echo "Waiting for repository $OWNER/$REPO_NAME to become available..." + sleep 4 + fi + done + + if ! gh api repos/$OWNER/$REPO_NAME > /dev/null 2>&1; then + echo "::warning::Repository $OWNER/$REPO_NAME did not become available after 5 attempts. Continuing anyway." + fi echo "REPO_NAME=$REPO_NAME" >> $GITHUB_ENV echo "OWNER=$OWNER" >> $GITHUB_ENV @@ -67,6 +96,7 @@ jobs: run: | if gh api orgs/$OWNER/teams > /dev/null 2>&1; then if ! gh api orgs/$OWNER/teams/$MAINTAINERS_TEAM > /dev/null 2>&1; then + # Retrieve the numeric ID of the 'maintainers' team to use as the parent_team_id MAINTAINERS_PARENT_ID=$(gh api orgs/$OWNER/teams/maintainers | jq -r '.id') MAINTAINERS_PARENT_ID_NUM=$(echo "$MAINTAINERS_PARENT_ID" | grep -o '[0-9]*') echo "Debug: MAINTAINERS_PARENT_ID_NUM=$MAINTAINERS_PARENT_ID_NUM" @@ -101,6 +131,10 @@ jobs: fi CODEOWNERS_LIST=$(echo "$CODEOWNERS_LIST" | xargs) + # Loop through each provided GitHub username and invite them to the codeowners team + # Note: users who are not yet members of the organization will be invited to join + # and will need to accept the invitation before they are part of the team and the CODEOWNERS file get fully valid + echo "Inviting users to team $CODEOWNERS_TEAM: [$CODEOWNERS_LIST]" for username in $CODEOWNERS_LIST; do clean_user=$(echo "$username" | sed 's/^@//') echo "Checking if @$clean_user is a valid GitHub user..." @@ -118,7 +152,7 @@ jobs: - name: Configure repository settings run: | gh repo edit $OWNER/$REPO_NAME \ - --description "$REPO_NAME" \ + --description "Sandbox API Repository for $REPO_NAME API(s)" \ --homepage "${{ github.event.inputs.repo_wiki_page }}" \ --add-topic sandbox-api-repository gh api -X PATCH repos/$OWNER/$REPO_NAME \ @@ -128,7 +162,8 @@ jobs: - name: Update README.md placeholders run: | - # changes the README.md from template repository and updates the README.md in the new repository with it + # Replace placeholders in the template README.md and push the updated version to the new repository + # Note: the README.md file is expected to be in the root of the repository sed -i "s/{{repo_name}}/$REPO_NAME/g" README.md sed -i "s|{{repo_wiki_page}}|${{ github.event.inputs.repo_wiki_page }}|g" README.md sed -i "s|{{subproject_name}}|${{ github.event.inputs.subproject_name }}|g" README.md @@ -136,6 +171,7 @@ jobs: sed -i "s|{{mailinglist_name}}|${{ github.event.inputs.mailinglist_name }}|g" README.md sed -i "s|{{initial_codeowners}}|${{ github.event.inputs.initial_codeowners }}|g" README.md + # Retry loop: waits for README.md to appear in the new repo (max 5 attempts) SHA="" for i in {1..5}; do SHA=$(gh api repos/$OWNER/$REPO_NAME/contents/README.md 2>/dev/null | jq -r '.sha') @@ -185,7 +221,10 @@ jobs: - name: Update CODEOWNERS file run: | - sed "s|{{initial_codeowners}}|$CODEOWNERS_LIST|g" templates/CODEOWNERS > CODEOWNERS + # Replace placeholder in CODEOWNERS template with actual list of codeowners + # Note: also users who are skipped during team invitation will be added to the CODEOWNERS file and + # might need to be corrected manually later and invited manually to the CODEOWNERS team + sed "s|{{initial_codeowners}}|$CODEOWNERS_LIST|g" templates/CODEOWNERS_TEMPLATE > CODEOWNERS CODEOWNERS_SHA=$(gh api repos/$OWNER/$REPO_NAME/contents/CODEOWNERS | jq -r '.sha') gh api repos/$OWNER/$REPO_NAME/contents/CODEOWNERS \ @@ -200,6 +239,7 @@ jobs: TEMPLATE_REPO=$(basename "${{ github.repository }}") echo "Fetching rulesets from $OWNER/$TEMPLATE_REPO" + # Fetch all rulesets defined in the template repository for later replication RULESETS=$(gh api repos/$OWNER/$TEMPLATE_REPO/rulesets \ -H "Accept: application/vnd.github+json" 2>/dev/null || echo "[]") @@ -236,3 +276,25 @@ jobs: gh issue comment "$ADMIN_ISSUE_URL" \ --body "βœ… Repository setup has been completed by automation. You may now proceed with the checklist." + - name: Cleanup setup artifacts from template repository + run: | + # Explicit list of files to remove after setup (e.g., templates and placeholders) + FILES_TO_DELETE=( + "templates/CODEOWNERS" + "templates/issues/initial-admin.md" + "templates/issues/initial-codeowners.md" + "templates/README.md" + ) + + for file in "${FILES_TO_DELETE[@]}"; do + if gh api repos/$OWNER/$REPO_NAME/contents/$file > /dev/null 2>&1; then + sha=$(gh api repos/$OWNER/$REPO_NAME/contents/$file | jq -r '.sha') + gh api repos/$OWNER/$REPO_NAME/contents/$file \ + -X DELETE \ + -F message="Remove $file from template repository" \ + -F sha="$sha" || echo "::error::Failed to delete $file" + echo "::notice::Deleted $file" + else + echo "::warning::File $file not found during cleanup. Skipping." + fi + done diff --git a/CODEOWNERS b/CODEOWNERS index 9449381..4739da7 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,4 +1,6 @@ -# This file provides an overview of code owners in this repository. +# This file provides an overview of code owners in this repository + +# Note: this is the actual CODEOWNERS file to protect the template repository. The CODEONWERS file in newly created repositories will be build based on /templates/CODEOWNERS_TEMPLATE # Each line is a file pattern followed by one or more owners. # The last matching pattern has the most precedence. diff --git a/README.md b/README.md index 73f6e70..db775ce 100644 --- a/README.md +++ b/README.md @@ -5,42 +5,45 @@ - + # {{repo_name}} > [!NOTE] -> What is this repository about and how to use it: +> What is this template repository about and how to use it: > -> * For codeowners of existing CAMARA repository as a sample how a CAMARA repository should look like, e.g. to update legacy repositories. Have a look specifically on the [code of the README.md](https://github.com/camaraproject/Template_API_Repository/blob/main/README.md?plain=1) for different variants and copy relevant parts into your repository. +> * For codeowners of existing CAMARA repository it is a sample how a CAMARA repository should look like, e.g. to update legacy repositories. Have a look specifically on the [code of the README.md](https://github.com/camaraproject/Template_API_Repository/blob/main/README.md?plain=1) for different variants and copy relevant parts into your repository. > * For CAMARA admins to create new (Sandbox) API repositories automated: Use the `setup-new-repo` workflow together with documentation in [templates/README.md](templates/README.md). > -> The following is the template README for a new independent Sandbox API repository, other variants are within the commented code. +> The following is the template README for a new independent Sandbox repositories, Sandbox repositories within a Sub Project, and Incubated Repositories. Further variants are within the commented code. +> +> This note must be deleted in newly created repositories + +--- + - + Sandbox API Repository to describe, develop, document, and test the {{repo_name}} Service API(s). The repository does not yet belong to a CAMARA Sub Project. * API Repository [wiki page]({{repo_wiki_page}}) - +--- + - - +--- + - @@ -49,7 +52,7 @@ Incubating API Repository to evolve and maintain the definitions and documentati Repository for xxx of the {{subproject_name}} Working Group" * Working Group [wiki home page]({{repo_wiki_page}}) -!! Update with concrete link + --> ## Scope diff --git a/templates/CODEOWNERS b/templates/CODEOWNERS_TEMPLATE similarity index 100% rename from templates/CODEOWNERS rename to templates/CODEOWNERS_TEMPLATE diff --git a/templates/README.md b/templates/README.md index dbf836f..26e8d03 100644 --- a/templates/README.md +++ b/templates/README.md @@ -1,110 +1,138 @@ -# πŸ“˜ Sandbox API Repository Creation Automation for CAMARA +# πŸ“˜ Automation for CAMARA API Repository Creation -This document describes how to use the GitHub Action in the `Template_API_Repository` to automate the setup of new API repositories within the CAMARA GitHub organization or within a personal namespace. +The automation workflow "Setup New Repository" simplifies the process of setting up a new CAMARA API repository, ensuring consistency across teams and reducing manual steps. + +This document describes how to use the GitHub Action in the `Template_API_Repository` to automate the setup of new API repositories within the [CAMARA GitHub organization](https://github.com/camaraproject). --- ## πŸš€ Purpose -To automate the initial setup of a new repository, including: +To automate the initial administrative setup of a new API repository, ensuring consistency and reducing manual work. This includes: -- Creating a new repository from the template -- Setting metadata and repository settings -- Creating teams and assigning permissions (if in an organization) -- Adding CODEOWNERS based on a template -- Posting issues with initial checklists -- Cleaning up setup artifacts (workflow + templates) - not yet implemented +- Creating a new public repository based on the template +- Setting repo description, topics, and metadata +- Creating and configuring teams +- Assigning repository permissions +- Updating the README with project-specific details +- Adding CODEOWNERS +- Creating initial administrative issues +- Cleaning up template files from the new repository --- ## βš™οΈ How to Use -1. Go to the **Actions** tab of your fork or the template repo -2. Trigger the **"Setup New Repository"** workflow manually using **workflow\_dispatch** -3. Fill in the following inputs: - -### πŸ”’ Inputs - -- `repo_name`: Name of the new repository to create -- `subproject_name`: Optional subproject/working group name -- `repo_wiki_page`: Link to the repository wiki -- `subproject_wiki_page`: Optional link to the subproject wiki -- `mailinglist_name`: Mailing list for project discussion -- `initial_codeowners`: Space-separated GitHub usernames with `@` (e.g., `@alice @bob`) +### πŸ›  Prerequisites for Administrators ---- +Before running the workflow, ensure the following are set up: -## πŸ“„ What It Does +1. **Environment Setup**: -### βœ… Repository + - A GitHub environment named `repo-setup` must exist in the template repository. -- Creates a new public repository from the template -- Sets description, homepage (to wiki), and topic `sandbox-api-repository` -- Enables issues and discussions, disables wiki +2. **Fine-Grained Personal Access Token (FGPAT)**: -### βœ… Teams + - A secret named `GH_REPO_CREATE_TOKEN` must be stored in the `repo-setup` environment. + - This token must be a **fine-grained personal access token** with access to both the template and target repositories. -- Creates `repo_name_maintainers` and `repo_name_codeowners` under parent teams (if applicable) -- Adds each codeowner to the CODEOWNERS team (if user exists) + #### πŸ” Required Token Permissions: -### βœ… Files + - **Contents**: Read and write + - **Issues**: Read and write + - **Metadata**: Read-only + - **Administration**: Read and write -- Replaces placeholders in `README.md` -- Generates CODEOWNERS from `templates/CODEOWNERS` -- Posts 2 issues using templates in `templates/issues/*.md` -- Adds a comment to the first issue confirming setup success + #### πŸ”§ How to Create a Fine-Grained Token: -### βœ… Rulesets + 1. Go to [GitHub Developer Settings – Fine-grained personal access tokens](https://github.com/settings/personal-access-tokens) + 2. Click **"Generate new token (fine-grained)"** + 3. Set **Resource owner** to your GitHub username (for testing) or organization (camaraproject) + 4. Choose **repositories to access**: all repositories (otherwise newly created repositories are not covered) + 5. Under **Repository permissions**, set: + - Contents β†’ Read and write + - Issues β†’ Read and write + - Metadata β†’ Read-only + - Administration β†’ Read and write + - Generate the token and copy it + 6. Add it as the `GH_REPO_CREATE_TOKEN` secret under **Settings > Environments > repo-setup** -- Sync rulesets from template repository +--- -### βœ… Cleanup (currently not implemented) +### ▢️ Running the Workflow -- Deletes the workflow file itself from the new repo -- Deletes all files inside the `templates/` folder +1. Go to the `Actions` tab of [`Template_API_Repository`](https://github.com/camaraproject/Template_API_Repository/actions) +2. Select the **"Setup New Repository"** workflow +3. Use the `workflow_dispatch` form to input the following values: ---- +#### πŸ”€ Inputs -## πŸ” Requirements +| Input | Required | Description | +| ---------------------- | -------- | ------------------------------------------------------------------------------------------------------------ | +| `repo_name` | βœ… | Name of the new repository to create | +| `subproject_name` | ❌ | Optional subproject or working group name | +| `repo_wiki_page` | βœ… | URL of the new repository's wiki page | +| `subproject_wiki_page` | ❌ | URL of the subproject’s wiki page (if applicable) | +| `mailinglist_name` | βœ… | Mailing list associated with the repo | +| `initial_codeowners` | βœ… | Space-separated GitHub usernames (with `@`). Ensure each user exists and can be invited to the organization. | -### πŸ”‘ GitHub Personal Access Token (PAT) +#### πŸ’‘ Example Input: -- Stored as repository or environment secret: `GH_REPO_CREATE_TOKEN` -- Must have scopes: - - `repo` - - `admin:org` (if using teams) +```text +repo_name: my-new-api +subproject_name: mobility +repo_wiki_page: https://github.com/camaraproject/my-new-api/wiki +subproject_wiki_page: https://github.com/camaraproject/mobility/wiki +mailinglist_name: mobility@lists.camaraproject.org +initial_codeowners: @alice @bob @charlie +``` -### πŸ›‘ Environment Restrictions +--- -- The workflow is restricted to run in a GitHub Environment: `repo-setup` -- That environment must be configured in **Settings β†’ Environments** -- Add the `@camaraproject/admins` team as required reviewers to control access -- Store the `GH_REPO_CREATE_TOKEN` secret inside this environment +## 🧱 What the Workflow Does + +This GitHub Actions workflow is defined in the `Template_API_Repository`, which serves as the starting point for all new API repositories in the CAMARA project. + +- Creates a new public repository using this template +- Waits until the repo is accessible +- Sets metadata: + - Description, homepage URL, topic `sandbox-api-repository` + - Enables discussions and issues; disables wiki +- Creates two teams: + - `repo_name_maintainers` (under `maintainers`) + - `repo_name_codeowners` (under `codeowners`) +- Assigns permissions: + - `triage` to maintainers + - `push` to codeowners + - `maintain` to admins +- Updates `README.md` using placeholder replacement +- Generates and commits a `CODEOWNERS` file from template +- Syncs all rulesets from the template repository +- Opens two issues: + - Initial administrative tasks + - Initial tasks for codeowners +- Deletes listed template files from the new repository --- -## πŸ“¦ Required Template Files - -The following must exist in the `Template_API_Repository`: +## βœ… What to Do After the Workflow -``` -templates/CODEOWNERS -templates/issues/initial-admin.md -templates/issues/initial-codeowners.md -``` +- Follow the instructions and checklist in the created issue "New Repository - Initial administrative tasks #1", especially: + - Review the newly created repository and ensure all README placeholders and metadata have been populated correctly + - Confirm that the CODEOWNERS file includes valid GitHub usernames. If users are not part of the organization, team invitations may not succeed + - Delete `.github/workflows/setup-new-repo.yml` manually from the new repository, as it is not removed automatically + - Note: Improvements of this checklist should go into `/templates/issues/initial-admin.md` --- -## πŸ§ͺ Testing Tips +## πŸ“Œ Future Enhancements -- Use a test repo name like `test-repo-$(date +%s)` to avoid naming collisions -- Run in a personal account if you want to skip org/team features -- Check your repo afterwards for: - - Metadata - - CODEOWNERS file - - Issue templates and comment - - Removed setup files +- Set the correct labels for issues and pull requests within the new repository +- Adding linting workflow (based on reusable workflow from `Tooling`Β repository) +- Validate usernames/org membership during CODEOWNERS setup +- Dry-run support for validation without creation +- Move the workflow out of the template repository into e.g. `.github` or `Tooling` repository (requires some rewriting of the workflow) --- -For questions, open an issue in the template repository or contact a CAMARA admin. +For questions or feedback, open an issue in [`Template_API_Repository`](https://github.com/camaraproject/Template_API_Repository/issues) or reach out via the mailing list [adm@lists.camaraproject.org](mailto\:adm@lists.camaraproject.org). diff --git a/templates/issues/initial-admin.md b/templates/issues/initial-admin.md index f9def62..d175ef0 100644 --- a/templates/issues/initial-admin.md +++ b/templates/issues/initial-admin.md @@ -2,10 +2,10 @@ - [ ] Review repository settings - [ ] Check that the CODEOWNERS file is valid (initial codeowners have accepted the invitation) -- [ ] Remove the content of /templates and the /.github/workflows/setup-new-repo.yml +- [ ] Remove /.github/workflows/setup-new-repo.yml in the new repository (as long as it is copied into it) - [ ] Update the README - choose the right badge (default: Sandbox) - - choose the right variant of text for Independent Sandbox / Sandbox in Sub Project / ... + - choose the right variant for Independent Sandboxes / Sandboxes in Sub Project / ... - check the wiki links for correctness - [ ] Assign the initial issue for CODEWONERS to the appropriate codeowners - [ ] Update the Onboarding Tracker within APIBacklog From 0637837c0258b82d5def5cab3945e45654fed1e3 Mon Sep 17 00:00:00 2001 From: Herbert Damker <52109189+hdamker@users.noreply.github.com> Date: Tue, 15 Apr 2025 15:57:05 +0200 Subject: [PATCH 2/3] README.md - minor corrections --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index db775ce..8898022 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ - + # {{repo_name}} @@ -34,7 +34,7 @@ Sandbox API Repository to describe, develop, document, and test the {{repo_name} --- -Sandbox API Repository to describe, develop, document, and test the {{repo_name}} Service API(s) within the Sub Project [{{subproject_name}}]({{subproject_wiki_page}}) +Sandbox API Repository to describe, develop, document, and test the {{repo_name}} Service API(s) within the Sub Project [{{subproject_name}}]({{subproject_wiki_page}}). * API Repository [wiki page]({{repo_wiki_page}}) From b56acc849bc1b832e5bb2938cb6e1bbc76e775fa Mon Sep 17 00:00:00 2001 From: Herbert Damker <52109189+hdamker@users.noreply.github.com> Date: Tue, 15 Apr 2025 16:01:08 +0200 Subject: [PATCH 3/3] Update initial-admin.md --- templates/issues/initial-admin.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/issues/initial-admin.md b/templates/issues/initial-admin.md index d175ef0..f4a2ba2 100644 --- a/templates/issues/initial-admin.md +++ b/templates/issues/initial-admin.md @@ -1,11 +1,11 @@ ## Initial Administrative Tasks -- [ ] Review repository settings -- [ ] Check that the CODEOWNERS file is valid (initial codeowners have accepted the invitation) +- [ ] Review repository settings, see [documentation of workflow](https://github.com/camaraproject/Template_API_Repository/tree/main/templates). +- [ ] Check that the CODEOWNERS file is valid (potential need to wait until initial codeowners have accepted the invitation) - [ ] Remove /.github/workflows/setup-new-repo.yml in the new repository (as long as it is copied into it) - [ ] Update the README - choose the right badge (default: Sandbox) - - choose the right variant for Independent Sandboxes / Sandboxes in Sub Project / ... + - choose the right variant for Independent Sandboxes,Sandboxes in Sub Project, Incubating, or repository for working group - check the wiki links for correctness - [ ] Assign the initial issue for CODEWONERS to the appropriate codeowners - [ ] Update the Onboarding Tracker within APIBacklog