GitHub Group Creation

Create GitHub group based on the provided group information

source

GitHubGroup

 GitHubGroup (credentials_fp='', org='', verbosity=1)

Initialize self. See help(type(self)) for accurate signature.

Type Default Details
credentials_fp str the file path to the credential json
org str the organization name
verbosity int 1 Controls the verbosity: 0=silent, 1=print status

GitHub Authentication

View this document for how to set up your GitHub Personal Access Token. (TODO: be sure to specify scopes)

Store the token information in a json file.

credentials_fp = "credentials.json"
with open(credentials_fp, "r") as f:
    # take a look at the token
    print(f.read())
g = GitHubGroup(credentials_fp=credentials_fp, org="COGS118A", verbosity=1)
{
  "GitHub Token": "token",
  "Canvas Token": "token"
}
Successfully Authenticated. GitHub account:  scott-yj-yang 
Target Organization Set:  COGS118A 

Optionally, you can instansiate a GitHubGroup object and authenticate yourself by calling the following method.


source

GitHubGroup.auth_github

 GitHubGroup.auth_github (credentials_fp:str)

Authenticate GitHub account with the provided credentials

Type Details
credentials_fp str the personal access token generated at GitHub Settings
g = GitHubGroup(verbosity=1) # you can set verbosity to 1 to see the current progress
g.auth_github(credentials_fp)
Successfully Authenticated. GitHub account:  scott-yj-yang 

GitHub Organization Settings

Usually, you want to create students repositories under a course GitHub organization. To set the target organization, you can call the following function.


source

GitHubGroup.set_org

 GitHubGroup.set_org (org:str)

Set the target organization for repo creation

Type Details
org str the target organization name
g.set_org("COGS118A")
Target Organization Set:  COGS118A 

Create GitHub Group in one Call


source

GitHubGroup.create_group_repo

 GitHubGroup.create_group_repo (repo_name:str,
                                collaborators:[<class'str'>],
                                permission:str, rename_files={},
                                repo_template='', private=True,
                                description='', team_slug='',
                                team_permission='', feedback_dir=False,
                                feedback_template_fp='')

Create a Group Repository

Type Default Details
repo_name str group repository name
collaborators [<class ‘str’>] list of collaborators GitHub id
permission str the permission of collaborators. pull, push or admin
rename_files dict {} dictionary of files renames {:}
repo_template str If empty string, an empty repo will be created. Put in the format of “/
private bool True visibility of the created repository
description str description for the GitHub repository
team_slug str team slug, add to this repo
team_permission str team permission to this repository pull, push or admin
feedback_dir bool False whether to create a feedback directory for each repository created
feedback_template_fp str the directory of the feedback template
Returns Repository created repository
repo = g.create_group_repo(
    repo_name="API_test_repo",
    collaborators=["jasongfleischer"],
    permission="admin",
    repo_template="COGS118A/group_template",
    rename_files={
        "Checkpoint_groupXXX.ipynb": "Checkpoint_group001.ipynb",
        "FinalProject_groupXXX.ipynb": "FinalProject_group001.ipynb",
        "Proposal_groupXXX.ipynb": "Proposal_group001.ipynb"
    },
    private=False,
    description="Test Creation of Group Repo for COGS118A final project group",
    team_slug="Instructors_Sp23",
    team_permission="admin"
)
Repo  API_test_repo  Created... Wait for 3 sec to updates
File Successfully Renamed from   Checkpoint_groupXXX.ipynb   to  Checkpoint_group001.ipynb 
File Successfully Renamed from   FinalProject_groupXXX.ipynb   to  FinalProject_group001.ipynb 
File Successfully Renamed from   Proposal_groupXXX.ipynb   to  Proposal_group001.ipynb 
Added Collaborator:  jasongfleischer  to:  API_test_repo  with permission:  admin 
Team  Instructors_Sp23  added to  API_test_repo  with permission  admin 
Group Repo:  API_test_repo  successfuly created!

Lower Level Methods

Belows are the components that faciliate the GitHubGroup.create_group_repo. If errors were prompted during group creation scripts, or simply you want more flexibility, you can call those components individually.

Create GitHub Repository

Note: GtiHubGroup.create_group_repo call this method to create a GitHub repository

personal_account argument controls the location of the repository creation. If set to False (default), it will create repository in the target organization. If set to True, the new repository will be created in the personal GitHub account.


source

GitHubGroup.create_repo

 GitHubGroup.create_repo (repo_name:str, repo_template='', private=True,
                          description='', personal_account=False)

Create a repository, either blank, or from a template

Type Default Details
repo_name str repository name
repo_template str template repository that new repo will use. If empty string, an empty repo will be created. Put in the format of “/
private bool True visibility of the created repository
description str description for the GitHub repository
personal_account bool False create repos in personal GitHub account
Returns Repository

Note: GtiHubGroup.create_group_repo call this method to create a GitHub repository

personal_account argument controls the location of the repository creation. If set to False (default), it will create repository in the target organization. If set to True, the new repository will be created in the personal GitHub account.

# create a repo under the org
repo = g.create_repo(
    "test-repo-organizational",
    private=True
)
print(repo)
Repository(full_name="COGS118A/test-repo-organizational")

As you can see from the full name COGS118A/test-repo, it is created under the organization of COGS118A.

Alternatively, I can also create a new repository under my personal account.

# create a repo under the my personal account
repo = g.create_repo(
    "test-repo-personal",
    private=True,
    personal_account=True
)
print(repo)
Repository(full_name="scott-yj-yang/test-repo-personal")
# create a repo under the my personal account
repo = g.create_repo(
    repo_name="test-repo-personal",
    private=True,
    personal_account=True
)
print(repo)
Repository(full_name="scott-yj-yang/test-repo-personal")

Create Repository from Template

You can also create a repository with a template repository. To do that, specify the full name of the template repository to the repo_template parameter. From the output, we can see that the repository test-repo-from-template is created with the template files.

# create a repo from a template
repo = g.create_repo(
    repo_name="test-repo-from-template",
    repo_template="COGS118A/group_template",
    private=True
)
print(repo)

# wait 3 sec for repository creation.
time.sleep(3)

print("\nThis Repository contains... \n")
pprint(repo.get_contents("."))
Repository(full_name="COGS118A/test-repo-from-template")

This Repository contains... 

[ContentFile(path=".gitignore"),
 ContentFile(path="Checkpoint_groupXXX.ipynb"),
 ContentFile(path="FinalProject_groupXXX.ipynb"),
 ContentFile(path="Proposal_groupXXX.ipynb"),
 ContentFile(path="README.md")]

Rename Files in the Repository

Usually, the template file names are generics and is not specific to a group. Under the context of group project, we want to rename each notebook files with thier group numbers. For example, for Group 1, we want to rename the file Checkpoint_groupXXX.ipynb to Checkpoint_group001.ipynb. To do that, we can use the following method.


source

GitHubGroup.rename_files

 GitHubGroup.rename_files (repo:github.Repository.Repository,
                           og_filename:str, new_filename:str)

Rename the file by delete the old file and commit the new file

Type Details
repo Repository the repository that we want to rename file
og_filename str old file name
new_filename str new file name

Note: This method simply delete the old files and create new files with the updated file name. Therefore, 2 commits for each file is expected. (1 for delete, 1 for re-upload). For example, if I want to rename 5 files, I will have 10 commits need to do in total.

g.rename_files(
    repo=repo,
    og_filename="Checkpoint_groupXXX.ipynb",
    new_filename="Checkpoint_group001.ipynb"
)
# take a look at new files
print("\nThis Repository contains... \n")
pprint(repo.get_contents("."))
File Successfully Renamed from   Checkpoint_groupXXX.ipynb   to  Checkpoint_group001.ipynb 

This Repository contains... 

[ContentFile(path=".gitignore"),
 ContentFile(path="Checkpoint_group001.ipynb"),
 ContentFile(path="FinalProject_groupXXX.ipynb"),
 ContentFile(path="Proposal_groupXXX.ipynb"),
 ContentFile(path="README.md")]

Notice that the files were renamed as expected.

Collaborators and Teams Access Repository

Once the repository was created, we need to give the student team members proper permission to write to the repository and instructional team to be the admin of the repository. Those two functionalities are achieve by the following two methods.


source

GitHubGroup.add_collaborator

 GitHubGroup.add_collaborator (repo:github.Repository.Repository,
                               collaborator:str, permission:str)

Add collaborator to the repository with specified permission

Type Details
repo Repository target repository
collaborator str GitHub username of the collaborator
permission str pull, push or admin
# add collaborator to the repository with push permission
g.add_collaborator(
    repo=repo,
    collaborator="Andrina-iris",
    permission="write"
)
Added Collaborator:  Andrina-iris  to:  test-repo-from-template  with permission:  write 

In almost every quarter, at least 10 students forgot to accept the invitation to join the group repository. Historially, our instructional team handle those student’s GitHub account on a case-by-case basis. However, with this module, it is possible to resent all pending and expired invitations to those students with one call.


source

GitHubGroup.resend_invitations

 GitHubGroup.resend_invitations (repo:github.Repository.Repository)

Resent Invitation to invitee who did not accept the invitation

Type Details
repo Repository target repository
Returns [<class ‘github.NamedUser.NamedUser’>] list of re-invited user

Students will receive an email from GitHub with the freshly made, unexpired invitation to their group repository.

g.resend_invitations(repo)
The list of pending invitation:
[NamedUser(login="Andrina-iris")]
 Andrina-iris Invite Revoked Andrina-iris 
Added Collaborator:  Andrina-iris  to:  test-repo-from-template  with permission:  write 
 Invite Resent to Andrina-iris 
[NamedUser(login="Andrina-iris")]

Additionally, course staffs should be in a team in the GitHub Organization in order to manage student repositories.


source

GitHubGroup.add_team

 GitHubGroup.add_team (repo:github.Repository.Repository, team_slug:str,
                       permission:str)

Add team to the repository with specified permission

Type Details
repo Repository target repository
team_slug str team slug (name)
permission str pull, push or admin
g.add_team(
    repo=repo,
    team_slug="Instructors_Sp23",
    permission="admin"
)
Team  Instructors_Sp23  added to  test-repo-from-template  with permission  admin 

If you have all the students repositories under the same team, you can use the following method to resent all pending invitations from all the repositories under that team.


source

GitHubGroup.resent_invitations_team_repos

 GitHubGroup.resent_invitations_team_repos (team_slug:str)

For all repository under that team, Resent invitation to invitee who did not accept the invitation

Type Details
team_slug str team slug (name) under the org
g.resent_invitations_team_repos(team_slug="Instructors_Sp23")
Repository  AssignmentNotebooksSource_SP23 :
The list of pending invitation:
[]
Repository  AssignmentNotebooks_SP23 :
The list of pending invitation:
[]
Repository  DiscussionSectionNotebooks :
The list of pending invitation:
[]
Repository  Dockerfiles :
The list of pending invitation:
[]
Repository  Lectures :
The list of pending invitation:
[]
Repository  Notebooks :
The list of pending invitation:
[]
Repository  test-repo-from-template :
The list of pending invitation:
[NamedUser(login="Andrina-iris")]
 Andrina-iris Invite Revoked Andrina-iris 
Added Collaborator:  Andrina-iris  to:  test-repo-from-template  with permission:  write 
 Invite Resent to Andrina-iris 

Project Feedback and GitHub Issues

Thanks for the group nature of the created repository, we can also use the created GitHub repository to create group project feedback to students via GitHub issues.

We can create a directory under the instructors’ computer. Each directory will have a folder for each group repository with the template file. The template files are usually the rubrics for the project grading.

TODO: add file superlink to the repo to see the examples.


source

GitHubGroup.create_feedback_dir

 GitHubGroup.create_feedback_dir (repo:github.Repository.Repository,
                                  template_fp:str, destination='feedback')

Create feedback directory on local machine

Type Default Details
repo Repository target repository
template_fp str
destination str feedback directory path of the template file.
g.create_feedback_dir(repo, "feedback_template")
# take a look at the generated tempalte files.
os.listdir(f"feedback/{repo.name}")
File checkpoint_feedback.md created at feedback/test-repo-from-template
File proposal_feedback.md created at feedback/test-repo-from-template
File final_project_feedback.md created at feedback/test-repo-from-template
['checkpoint_feedback.md', 'proposal_feedback.md', 'final_project_feedback.md']

After created the project feedback, instructional team can modify the markdown rubrics and provide feedback to students via GitHub issue.


source

GitHubGroup.create_issue

 GitHubGroup.create_issue (repo:github.Repository.Repository, title:str,
                           content:str)

Create GitHub issue to the target repository

Type Details
repo Repository target repository
title str title of the issue,
content str content of the issue
Returns Issue open issue
# create a test issue
issue = g.create_issue(repo, "Test Issue", "This is just a test issue.")
issue
In the repo: test-repo-from-template,
Issue Test Issue Created!
Issue(title="Test Issue", number=1)

Alternatively, you can create issue from markdown files, where it contains all the comments and rubrics for this project. The first line of the markdown file will be the title of the github issue.


source

GitHubGroup.create_issue_from_md

 GitHubGroup.create_issue_from_md (repo:github.Repository.Repository,
                                   md_fp:str)

Create GitHub issue from markdown file.

Type Details
repo Repository target repository,
md_fp str file path of the feedback markdown file
Returns Issue open issue
issue = g.create_issue_from_md(repo, "feedback_template/proposal_feedback.md")
issue
In the repo: test-repo-from-template,
Issue  Project Proposal Feedback Created!
Issue(title=" Project Proposal Feedback", number=2)

Release Feedback in Batch

During projct grading, we will handle numerous groups at once. Once the instructor team finish modifying the markdown file for each group, we can release feedback to each of the project repository, as long as they have the same file name. For example, we have finish grading the final project, in the file name of feedback/<repo_name>/final_project_feedback.md, and they are ready to be publish, we can call the following function to create issue in batch.


source

GitHubGroup.release_feedback

 GitHubGroup.release_feedback (md_filename:str, feedback_dir='feedback')

Release feedback via GitHub issue from all the feedbacks in the feedback directory

Type Default Details
md_filename str feedback markdown file name
feedback_dir str feedback feedback directory contains the markdown files
g.release_feedback("final_project_feedback.md")
In the repo: test-repo-from-template,
Issue  Final Project Feedback Created!