1+ import os
2+ import requests
3+ import base64
4+ from datetime import datetime
5+
6+ # GitHub API endpoint to list repositories in an organisation
7+ REPOS_URL = "https://api.github.com/orgs/{org}/repos"
8+
9+ # GitHub API endpoint to get the contents of a file in a repository
10+ FILE_URL = "https://api.github.com/repos/{org}/{repo}/contents/{path}"
11+
12+ # GitHub API endpoint to create a file in a repository
13+ CREATE_URL = "https://api.github.com/repos/{org}/{repo}/contents/{path}"
14+
15+ # GitHub API endpoint to delete a file in a repository
16+ DELETE_URL = "https://api.github.com/repos/{org}/{repo}/contents/{path}"
17+
18+ # GitHub token for authentication
19+ GITHUB_TOKEN = os .getenv ("GITHUB_TOKEN" )
20+
21+ # Organisation name
22+ ORG_NAME = os .getenv ("ORG_NAME" )
23+
24+ # Copyright owner name
25+ COPYRIGHT_OWNER = os .getenv ("COPYRIGHT_OWNER" )
26+
27+ # Current year
28+ CURRENT_YEAR = datetime .now ().year
29+
30+ # Headers for GitHub API requests
31+ HEADERS = {
32+ "Authorization" : f"token { GITHUB_TOKEN } " ,
33+ "Accept" : "application/vnd.github.v3+json"
34+ }
35+
36+ # URL to fetch the Apache 2.0 licence text
37+ APACHE_LICENCE_URL = "https://www.apache.org/licenses/LICENSE-2.0.txt"
38+
39+ def get_repositories (org ):
40+ response = requests .get (REPOS_URL .format (org = org ), headers = HEADERS )
41+ response .raise_for_status ()
42+ return response .json ()
43+
44+ def get_file_contents (org , repo , path ):
45+ response = requests .get (FILE_URL .format (org = org , repo = repo , path = path ), headers = HEADERS )
46+ if response .status_code == 404 :
47+ return None
48+ response .raise_for_status ()
49+ return response .json ()
50+
51+ def create_file (org , repo , path , content ):
52+ data = {
53+ "message" : "Add Apache 2.0 licence" ,
54+ "content" : content
55+ }
56+ response = requests .put (CREATE_URL .format (org = org , repo = repo , path = path ), headers = HEADERS , json = data )
57+ response .raise_for_status ()
58+
59+ def update_file (org , repo , path , content , sha ):
60+ data = {
61+ "message" : "Update licence with current year and copyright owner" ,
62+ "content" : content ,
63+ "sha" : sha
64+ }
65+ response = requests .put (CREATE_URL .format (org = org , repo = repo , path = path ), headers = HEADERS , json = data )
66+ response .raise_for_status ()
67+
68+ def delete_file (org , repo , path , sha ):
69+ data = {
70+ "message" : "Rename LICENSE to LICENCE" ,
71+ "sha" : sha
72+ }
73+ response = requests .delete (DELETE_URL .format (org = org , repo = repo , path = path ), headers = HEADERS , json = data )
74+ response .raise_for_status ()
75+
76+ def fetch_apache_licence ():
77+ response = requests .get (APACHE_LICENCE_URL )
78+ response .raise_for_status ()
79+ return response .text
80+
81+ def main ():
82+ repos = get_repositories (ORG_NAME )
83+ apache_licence_text = fetch_apache_licence ()
84+
85+ for repo in repos :
86+ repo_name = repo ["name" ]
87+ licence_file = get_file_contents (ORG_NAME , repo_name , "LICENCE" )
88+ license_file = get_file_contents (ORG_NAME , repo_name , "LICENSE" )
89+
90+ if licence_file is None and license_file is None :
91+ print (f"No LICENCE or LICENSE file found in { repo_name } , adding Apache 2.0 licence" )
92+ # Encode the Apache 2.0 licence text to base64
93+ encoded_licence = base64 .b64encode (apache_licence_text .encode ("utf-8" )).decode ("utf-8" )
94+ # Create the LICENCE file in the repository
95+ create_file (ORG_NAME , repo_name , "LICENCE" , encoded_licence )
96+ continue
97+
98+ if license_file is not None :
99+ # Rename LICENSE to LICENCE
100+ content = license_file ["content" ]
101+ sha = license_file ["sha" ]
102+ delete_file (ORG_NAME , repo_name , "LICENSE" , sha )
103+ create_file (ORG_NAME , repo_name , "LICENCE" , content )
104+ print (f"Renamed LICENSE to LICENCE in { repo_name } " )
105+
106+ content = licence_file ["content" ]
107+ sha = licence_file ["sha" ]
108+ decoded_content = base64 .b64decode (content ).decode ("utf-8" )
109+
110+ # Check if the year is not the current year and update it
111+ if f"{ CURRENT_YEAR } { COPYRIGHT_OWNER } " not in decoded_content :
112+ # Update the licence content with the current year and copyright owner
113+ updated_content = decoded_content .replace (
114+ "[yyyy] [name of copyright owner]" ,
115+ f"{ CURRENT_YEAR } { COPYRIGHT_OWNER } "
116+ )
117+ else :
118+ updated_content = decoded_content
119+
120+ # Encode the updated content back to base64
121+ encoded_content = base64 .b64encode (updated_content .encode ("utf-8" )).decode ("utf-8" )
122+
123+ # Update the file in the repository
124+ update_file (ORG_NAME , repo_name , "LICENCE" , encoded_content , sha )
125+ print (f"Updated LICENCE file in { repo_name } " )
126+
127+ if __name__ == "__main__" :
128+ main ()
0 commit comments