Skip to content

Commit 6cccd91

Browse files
authored
Merge pull request #19 from hdamker/setup-repo-automation
Setup repo automation
2 parents b0477df + 8f7821f commit 6cccd91

7 files changed

Lines changed: 382 additions & 34 deletions

File tree

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
# .github/workflows/setup-new-repo.yml
2+
name: Setup New Repository
3+
4+
on:
5+
workflow_dispatch:
6+
inputs:
7+
repo_name:
8+
description: 'Name of the new repository to create'
9+
required: true
10+
subproject_name:
11+
description: 'Optional subproject/working group name (leave empty for independent sandbox repo)'
12+
required: false
13+
repo_wiki_page:
14+
description: 'URL of the repository wiki page'
15+
required: true
16+
subproject_wiki_page:
17+
description: 'Optional URL of the subproject wiki page'
18+
required: false
19+
mailinglist_name:
20+
description: 'Mailing list name'
21+
required: true
22+
initial_codeowners:
23+
description: 'Space-separated GitHub usernames (with @) for initial CODEOWNERS'
24+
required: true
25+
26+
jobs:
27+
setup:
28+
runs-on: ubuntu-latest
29+
environment: repo-setup
30+
permissions:
31+
issues: write
32+
contents: write
33+
actions: write
34+
pull-requests: write
35+
36+
steps:
37+
38+
- name: Checkout template repository
39+
uses: actions/checkout@v4
40+
41+
- name: Set up GitHub CLI token with personal access token
42+
run: |
43+
echo "GH_TOKEN=${{ secrets.GH_REPO_CREATE_TOKEN }}" >> $GITHUB_ENV
44+
echo "Token GH_REPO_CREATE_TOKEN ready for use in GitHub CLI"
45+
46+
- name: Create new repository and set variables
47+
run: |
48+
REPO_NAME=${{ github.event.inputs.repo_name }}
49+
OWNER=$(echo '${{ github.repository }}' | cut -d'/' -f1)
50+
51+
echo "Checking if repository $OWNER/$REPO_NAME already exists..."
52+
if gh api repos/$OWNER/$REPO_NAME > /dev/null 2>&1; then
53+
echo "::error::Repository $OWNER/$REPO_NAME already exists. Exiting."
54+
exit 1
55+
fi
56+
57+
echo "Creating new repository: https://github.com/$OWNER/$REPO_NAME"
58+
gh repo create "$OWNER/$REPO_NAME" --public --template "$OWNER/$(basename '${{ github.repository }}')" --confirm
59+
60+
echo "REPO_NAME=$REPO_NAME" >> $GITHUB_ENV
61+
echo "OWNER=$OWNER" >> $GITHUB_ENV
62+
echo "MAINTAINERS_TEAM=${REPO_NAME}_maintainers" >> $GITHUB_ENV
63+
echo "CODEOWNERS_TEAM=${REPO_NAME}_codeowners" >> $GITHUB_ENV
64+
echo "CODEOWNERS_LIST=${{ github.event.inputs.initial_codeowners }}" >> $GITHUB_ENV
65+
66+
- name: Create teams
67+
run: |
68+
if gh api orgs/$OWNER/teams > /dev/null 2>&1; then
69+
if ! gh api orgs/$OWNER/teams/$MAINTAINERS_TEAM > /dev/null 2>&1; then
70+
gh api orgs/$OWNER/teams -f name="$MAINTAINERS_TEAM" -f parent_team_id="maintainers"
71+
else
72+
echo "Team $MAINTAINERS_TEAM already exists. Skipping creation."
73+
fi
74+
75+
if ! gh api orgs/$OWNER/teams/$CODEOWNERS_TEAM > /dev/null 2>&1; then
76+
gh api orgs/$OWNER/teams -f name="$CODEOWNERS_TEAM" -f parent_team_id="codeowners"
77+
else
78+
echo "Team $CODEOWNERS_TEAM already exists. Skipping creation."
79+
fi
80+
81+
CODEOWNERS_LIST=$(echo "$CODEOWNERS_LIST" | xargs)
82+
for username in $CODEOWNERS_LIST; do
83+
clean_user=$(echo "$username" | sed 's/^@//')
84+
echo "Checking if @$clean_user is a valid GitHub user..."
85+
if gh api users/$clean_user > /dev/null 2>&1; then
86+
echo "Inviting @$clean_user to team $CODEOWNERS_TEAM"
87+
gh api orgs/$OWNER/teams/$CODEOWNERS_TEAM/memberships/$clean_user -X PUT -f role=member || echo "Failed to invite $clean_user"
88+
else
89+
echo "::warning::User @$clean_user does not exist or cannot be looked up. Skipping."
90+
fi
91+
done
92+
else
93+
echo "Skipping team creation — not running in an organization."
94+
fi
95+
96+
- name: Configure repository settings
97+
run: |
98+
gh repo edit $OWNER/$REPO_NAME \
99+
--description "$REPO_NAME" \
100+
--homepage "${{ github.event.inputs.repo_wiki_page }}" \
101+
--add-topic sandbox-api-repository
102+
gh api -X PATCH repos/$OWNER/$REPO_NAME \
103+
-F has_discussions=true \
104+
-F has_issues=true \
105+
-F has_wiki=false
106+
107+
- name: Update README.md placeholders
108+
run: |
109+
# changes the README.md from template repository and updates the README.md in the new repository with it
110+
sed -i "s/{{repo_name}}/$REPO_NAME/g" README.md
111+
sed -i "s|{{repo_wiki_page}}|${{ github.event.inputs.repo_wiki_page }}|g" README.md
112+
sed -i "s|{{subproject_name}}|${{ github.event.inputs.subproject_name }}|g" README.md
113+
sed -i "s|{{subproject_wiki_page}}|${{ github.event.inputs.subproject_wiki_page }}|g" README.md
114+
sed -i "s|{{mailinglist_name}}|${{ github.event.inputs.mailinglist_name }}|g" README.md
115+
sed -i "s|{{initial_codeowners}}|${{ github.event.inputs.initial_codeowners }}|g" README.md
116+
117+
SHA=""
118+
for i in {1..5}; do
119+
SHA=$(gh api repos/$OWNER/$REPO_NAME/contents/README.md 2>/dev/null | jq -r '.sha')
120+
if [ "$SHA" != "null" ] && [ -n "$SHA" ]; then
121+
echo "Found README.md sha: $SHA"
122+
break
123+
else
124+
echo "README.md not yet available, retrying in 2s..."
125+
sleep 2
126+
fi
127+
done
128+
129+
gh api repos/$OWNER/$REPO_NAME/contents/README.md \
130+
-X PUT \
131+
-F message='Update README.md with project metadata' \
132+
-F content="$(base64 -w 0 README.md)" \
133+
-F sha="$SHA"
134+
135+
- name: Set team permissions
136+
run: |
137+
if gh api orgs/$OWNER/teams > /dev/null 2>&1; then
138+
gh api orgs/$OWNER/teams/$MAINTAINERS_TEAM/repos/$OWNER/$REPO_NAME -f permission=triage
139+
gh api orgs/$OWNER/teams/$CODEOWNERS_TEAM/repos/$OWNER/$REPO_NAME -f permission=write
140+
gh api orgs/$OWNER/teams/admins/repos/$OWNER/$REPO_NAME -f permission=maintain
141+
else
142+
echo "Skipping team permission assignment — not running in an organization."
143+
fi
144+
145+
- name: Update CODEOWNERS file
146+
run: |
147+
sed "s|{{initial_codeowners}}|$CODEOWNERS_LIST|g" templates/CODEOWNERS > CODEOWNERS
148+
CODEOWNERS_SHA=$(gh api repos/$OWNER/$REPO_NAME/contents/CODEOWNERS | jq -r '.sha')
149+
150+
gh api repos/$OWNER/$REPO_NAME/contents/CODEOWNERS \
151+
-X PUT \
152+
-F message='Update CODEOWNERS from template' \
153+
-F content="$(base64 -w 0 CODEOWNERS)" \
154+
-F sha="$CODEOWNERS_SHA"
155+
156+
157+
- name: Sync rulesets from template repository
158+
run: |
159+
TEMPLATE_REPO=$(basename "${{ github.repository }}")
160+
echo "Fetching rulesets from $OWNER/$TEMPLATE_REPO"
161+
162+
# Fetch rulesets once and store them in a variable
163+
RULESETS=$(gh api repos/$OWNER/$TEMPLATE_REPO/rulesets \
164+
-H "Accept: application/vnd.github+json" 2>/dev/null || echo "[]")
165+
if ! echo "$RULESETS" | jq -e 'type == "array" and length > 0' > /dev/null; then
166+
echo "No valid rulesets array found in template repository. Skipping."
167+
exit 0
168+
fi
169+
170+
# Process the fetched rulesets
171+
echo "$RULESETS" | jq -c '.[]' | while read -r ruleset; do
172+
NAME=$(echo "$ruleset" | jq -r '.name')
173+
echo "Syncing ruleset: $NAME"
174+
PAYLOAD=$(echo "$ruleset" | jq 'del(.id, .repository_id, .creator, .created_at, .updated_at)')
175+
echo "$PAYLOAD" > ruleset.json
176+
177+
gh api repos/$OWNER/$REPO_NAME/rulesets \
178+
-X POST \
179+
-H "Accept: application/vnd.github+json" \
180+
--input ruleset.json || echo "Warning: Failed to apply ruleset $NAME"
181+
done
182+
183+
- name: Create initial issues
184+
run: |
185+
ADMIN_ISSUE_URL=$(gh issue create --repo $OWNER/$REPO_NAME \
186+
--title "Initial administrative tasks" \
187+
--body "$(cat templates/issues/initial-admin.md)")
188+
189+
gh issue create --repo $OWNER/$REPO_NAME \
190+
--title "Initial tasks for codeowners" \
191+
--body "$(cat templates/issues/initial-codeowners.md)"
192+
193+
gh issue comment "$ADMIN_ISSUE_URL" \
194+
--body "✅ Repository setup has been completed by automation. You may now proceed with the checklist."
195+

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.DS_Store

README.md

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,83 @@
1-
<a href="https://github.com/camaraproject/§repo_name§/commits/" title="Last Commit"><img src="https://img.shields.io/github/last-commit/camaraproject/§repo_name§?style=plastic"></a>
2-
<a href="https://github.com/camaraproject/§repo_name§/issues" title="Open Issues"><img src="https://img.shields.io/github/issues/camaraproject/§repo_name§?style=plastic"></a>
3-
<a href="https://github.com/camaraproject/§repo_name§/pulls" title="Open Pull Requests"><img src="https://img.shields.io/github/issues-pr/camaraproject/§repo_name§?style=plastic"></a>
4-
<a href="https://github.com/camaraproject/§repo_name§/graphs/contributors" title="Contributors"><img src="https://img.shields.io/github/contributors/camaraproject/§repo_name§?style=plastic"></a>
5-
<a href="https://github.com/camaraproject/§repo_name§" title="Repo Size"><img src="https://img.shields.io/github/repo-size/camaraproject/§repo_name§?style=plastic"></a>
6-
<a href="https://github.com/camaraproject/§repo_name§/blob/main/LICENSE" title="License"><img src="https://img.shields.io/badge/License-Apache%202.0-green.svg?style=plastic"></a>
7-
<a href="https://github.com/camaraproject/§repo_name§/releases/latest" title="Latest Release"><img src="https://img.shields.io/github/release/camaraproject/§repo_name§?style=plastic"></a>
8-
!! Choose one of the following alternatives and then delete the task:
1+
<a href="https://github.com/camaraproject/{{repo_name}}/commits/" title="Last Commit"><img src="https://img.shields.io/github/last-commit/camaraproject/{{repo_name}}?style=plastic"></a>
2+
<a href="https://github.com/camaraproject/{{repo_name}}/issues" title="Open Issues"><img src="https://img.shields.io/github/issues/camaraproject/{{repo_name}}?style=plastic"></a>
3+
<a href="https://github.com/camaraproject/{{repo_name}}/pulls" title="Open Pull Requests"><img src="https://img.shields.io/github/issues-pr/camaraproject/{{repo_name}}?style=plastic"></a>
4+
<a href="https://github.com/camaraproject/{{repo_name}}/graphs/contributors" title="Contributors"><img src="https://img.shields.io/github/contributors/camaraproject/{{repo_name}}?style=plastic"></a>
5+
<a href="https://github.com/camaraproject/{{repo_name}}" title="Repo Size"><img src="https://img.shields.io/github/repo-size/camaraproject/{{repo_name}}?style=plastic"></a>
6+
<a href="https://github.com/camaraproject/{{repo_name}}/blob/main/LICENSE" title="License"><img src="https://img.shields.io/badge/License-Apache%202.0-green.svg?style=plastic"></a>
7+
<a href="https://github.com/camaraproject/{{repo_name}}/releases/latest" title="Latest Release"><img src="https://img.shields.io/github/release/camaraproject/{{repo_name}}?style=plastic"></a>
8+
<!-- Choose one of the following alternatives and then delete the task -->
99
<a href="https://github.com/camaraproject/Governance/blob/main/ProjectStructureAndRoles.md" title="Sandbox API Repository"><img src="https://img.shields.io/badge/Sandbox%20API%20Repository-yellow?style=plastic"></a>
1010
<a href="https://github.com/camaraproject/Governance/blob/main/ProjectStructureAndRoles.md" title="Incubating API Repository"><img src="https://img.shields.io/badge/Incubating%20API%20Repository-green?style=plastic"></a>
1111
<a href="https://github.com/camaraproject/Governance/blob/main/ProjectStructureAndRoles.md" title="Graduated API Repository"><img src="https://img.shields.io/badge/Graduated%20API%20Repository-silver?style=plastic"></a>
1212
<a href="https://github.com/camaraproject/Governance/blob/main/ProjectStructureAndRoles.md" title="Working Group"><img src="https://img.shields.io/badge/Working%20Group-red?style=plastic"></a>
1313

14+
# {{repo_name}}
1415

15-
# §repo_name§
16-
17-
18-
!! Uncomment if needed one of the alternatives and replace the links with the concrete links into the CAMARA wiki - then delete the task:
16+
> [!NOTE]
17+
> What is this repository about and how to use it:
18+
>
19+
> * 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.
20+
> * 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).
21+
>
22+
> The following is the template README for a new independent Sandbox API repository, other variants are within the commented code.
1923
2024
<!-- Alternative for new, independent Sandbox API Repositories -->
21-
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.
22-
23-
* API Repository [wiki page](https://lf-camaraproject.atlassian.net/wiki/x/AgDe) !! Update with concrete link when available and delete the task
25+
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.
2426

27+
* API Repository [wiki page]({{repo_wiki_page}})
2528

26-
<!-- Alternative for Sandbox API Repositories within the context of an existing Sub Project
27-
Sandbox API Repository to describe, develop, document, and test the §repo_name§ Service API(s) within the Sub Project [$Sub Project Name§](https://lf-camaraproject.atlassian.net/wiki/x/AgDe)
29+
<!-- Alternative for Sandbox API Repositories within the context of an existing Sub Project -->
2830

29-
* API Repository [wiki page](https://lf-camaraproject.atlassian.net/wiki/x/AgDe) !! Update with concrete link when available and delete the task
31+
<!--
32+
Sandbox API Repository to describe, develop, document, and test the {{repo_name}} Service API(s) within the Sub Project [{{subproject_name}}]({{subproject_wiki_page}})
3033
34+
* API Repository [wiki page]({{repo_wiki_page}})
3135
-->
3236

33-
<!-- Alternative for Incubating API Repositories (always part of Sub Project, potentially created as part of the Incubation):
37+
<!-- Alternative for Incubating API Repositories (always part of Sub Project, potentially created as part of the Incubation) -->
3438

35-
Incubating API Repository to evolve and maintain the definitions and documentation of §repo_name§ Service API(s) within the Sub Project [$Sub Project Name§](https://wiki.camaraproject.org/display/CAM/Sub+Projects)
39+
<!--
40+
Incubating API Repository to evolve and maintain the definitions and documentation of {{repo_name}} Service API(s) within the Sub Project [{{subproject_name}}]({{subproject_wiki_page}})
3641
37-
* API Repository [wiki page](https://lf-camaraproject.atlassian.net/wiki/x/AgDe) !! Update with concrete link when available and delete the task
42+
* API Repository [wiki page]({{repo_wiki_page}})
3843
-->
3944

4045
<!-- for Graduation of an API Repository replace "Incubating" with "Graduated" and don't forget to exchange the badge :-) -->
4146

4247
<!-- Alternative if the repository will be used for a working group - in this case further points, e.g. the scope, of this template need to be adapted:
4348
44-
Repository for xxx of the $Working Group$ Working Group"
49+
Repository for xxx of the {{subproject_name}} Working Group"
4550
46-
* Working Group [wiki home page](https://lf-camaraproject.atlassian.net/wiki/x/AgDe)
51+
* Working Group [wiki home page]({{repo_wiki_page}})
4752
!! Update with concrete link
4853
-->
4954

5055
## Scope
5156

52-
* Service API(s) “§repo_name§” (see APIBacklog.md)
57+
* Service API(s) “{{repo_name}}” (see APIBacklog.md)
5358
* The API(s) provide(s) the API consumer with the ability to:
5459
* §Short API scope description§ !! Add here a scope description according to the API proposal
5560
* Describe, develop, document, and test the API(s)
5661
* Started: §start date§
57-
<!-- * Incubating stage since: §incubation date$ -->
62+
<!-- * Incubating stage since: {{incubation date}} -->
5863

5964
## Release Information
6065

6166
The repository has no (pre)releases yet, work in progress is within the main branch.
6267
<!-- Optional: an explicit listing of the latest (pre-)release with additional information, e.g. links to the API definitions -->
6368
<!-- In addition use/uncomment one or multiple the following alternative options when becoming applicable -->
64-
<!-- Pre-releases of this sub project are available in https://github.com/camaraproject/§repo_name§/releases -->
65-
<!-- The latest public release is available here: https://github.com/camaraproject/§repo_name§/releases/latest -->
66-
<!-- For changes see [CHANGELOG.md](https://github.com/camaraproject/§repo_name§/blob/main/CHANGELOG.md) -->
69+
<!-- Pre-releases of this sub project are available in https://github.com/camaraproject/{{repo_name}}/releases -->
70+
<!-- The latest public release is available here: https://github.com/camaraproject/{{repo_name}}/releases/latest -->
71+
<!-- For changes see [CHANGELOG.md](https://github.com/camaraproject/{{repo_name}}/blob/main/CHANGELOG.md) -->
6772

6873
## Contributing
74+
6975
* Meetings are held virtually <!-- for new, independent Sandbox API repositories request a meeting link from the LF admin team or replace the information with the existing meeting information of the Sub Project -->
70-
* Schedule: !! tbd
71-
* [Registration / Join](https://zoom-lfx.platform.linuxfoundation.org/meetings/telcoapi) !! Update this link with your meeting registration/join link and delete the task
72-
* Minutes: Access [meeting minutes](https://lf-camaraproject.atlassian.net/wiki/x/AgDe) !! update this link to your wiki page using the "Share" link and delete the task
76+
77+
* Schedule: !! tbd
78+
* [Registration / Join](https://zoom-lfx.platform.linuxfoundation.org/meetings/telcoapi) !! Update this link with your meeting registration/join link and delete the task
79+
* Minutes: Access [meeting minutes]({{repo_wiki_page}}) !! update this link to your minutes archive page using the "Share" link and delete the task
7380
* Mailing List
74-
<!-- Note: the $mailinglistname$ is either already existing (for API Repositories within a Sub Projects) or will be created by the CAMARA Admin Team. -->
75-
* Subscribe / Unsubscribe to the mailing list <https://lists.camaraproject.org/g/$mailinglistname§>.
76-
* A message to the community of this Sub Project can be sent using <$mailinglistname§@lists.camaraproject.org>.
81+
<!-- Note: the `mailinglistname` is either already existing (for API Repositories within a Sub Projects) or will be created by the CAMARA Admin Team. -->
82+
* Subscribe / Unsubscribe to the mailing list <https://lists.camaraproject.org/g/{{mailinglist_name}}>.
83+
* A message to the community of this Sub Project can be sent using <{{mailinglist_name}}@lists.camaraproject.org>.

templates/CODEOWNERS

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# This file provides an overview of code owners in this repository.
2+
3+
# Each line is a file pattern followed by one or more owners.
4+
# The last matching pattern has the most precedence.
5+
# For more details, read the following article on GitHub: https://help.github.com/articles/about-codeowners/.
6+
7+
# These are the default owners for the whole content of this repository. The default owners are automatically added as reviewers when you open a pull request, unless different owners are specified in the file.
8+
# Replace the following line with "* @codeowner1 @codeowner2 @codeowner3" with the individual codeowner user names (the CODEOWNER file is the source of truth for the sub project codeowner team)
9+
* {{initial_codeowners}}
10+
11+
# Owners of the CODEOWNER and Maintainer.md files are the admins of CAMARA (to allow them to keep the teams within the CAMARA organization in sync in case of changes)
12+
/CODEOWNERS @camaraproject/admins
13+
/MAINTAINERS.MD @camaraproject/admins

0 commit comments

Comments
 (0)