Propagate Steps
Base Class
All propagate steps must inherit from/implement the following base class
(with some repeated from FlowStep
)
- class flow.flow_steps.FlowPropagateStep[RecordType]
A flow step to make external changes based on our records.
Parent Class:
FlowStep
- abstract class property description: str
A high-level description of the step
- abstract class property config_types: list[tuple[str, Type[ValidConfigTypes], str]]
The types of the configurations for the step. Each tuple in the list should include the name, type, and description of a configuration (respectively). See
FlowStep
- abstractmethod validate() None
This function should inspect the object’s
configs
attribute, and perform any static validation possible.
- abstractmethod propagate_records(records: list[tuple[RecordType, allocate_lock]], logger: Callable[[str], None], get_metadata: Callable[[str], Any], set_metadata: Callable[[str, Any], None], debug: bool = False) None
Propagate our records to update any external entities.
- Parameters:
records (list[tuple[RecordType, Lock]]) – The list of records to manipulate
logger (Callable[[str], None]) – A function to log any notable events
get_metadata (Callable[[str], Any],) – A function to retrieve global metadata previously set in the flow
set_metadata (Callable[[str, Any], None]) – A function to set global metadata within the flow
debug (bool, optional) – Whether we are in “debug” mode. In debug mode, no external state should be modified, and we are free to inject dummy information. Defaults to False.
Implementations
- class canvas_steps.assign_groups.AssignGroups
A propagate step to assign students to a group on Canvas.
This step takes in a current Canvas group (likely with some self-grouping), and pairs up remaining students to form lab groups. Groups are made to ensure that pairs are in the same lab section. Odd numbers are resolved by forming a group of three.
Lab sections
Lab sections are identified by having the string
LAB
in the name. Students will only be paired if they are in such a section; if no lab sections exist, no new pairings will be done.Note that current groups are NOT checked to see whether they are groups of fewer than three; the Canvas group can be configured to restrict this. However, solo students in a group are removed and re-assigned. This also has the side-benefit that if a student drops, the remaining partner is re-assigned to another group automatically. If an instructor wishes to disable this, they should disable the step.
The Canvas group (as well as our records) will be updated with the new group mapping.
Supported record types:
StudentRecord
Sets metadata:
old_groups
- configs.group_category: str
The category to reference/pair students in on Canvas
- configs.canvas_group_regex: str
The regex to extract group numbers from Canvas group names. The number will be the first matching group in the regex (ex.
ECE 2300: Lab Group (\d+)
). Use single-quotes in the YAML file to specify
- configs.form_date: datetime.datetime
When groups should be formed and logged. No groups will be formed or logged before then
- canvas_group_pattern
The format to make new Canvas groups with. Instances of
<num>
will be replaced with the group number. This should be complementary withcanvas_group_regex
- class canvas_steps.ping_join_group.PingJoinGroup
Ping users who haven’t joined a group on Canvas.
This step uses Gmail to send an email to students who haven’t yet joined a configured group on Canvas
Supported record types:
StudentRecord
- configs.start_date: datetime.datetime
The date when email notifications should start (none will be sent before this date)
- configs.email_gap: int
The number of days to wait between notifications.
- configs.email_template: str
The path to a template email (in the form of a text file). Instances of
<first_name>
and<last_name>
will be replaced appropriately for each notification.
- configs.group_category: str
The category to check on Canvas
- configs.send_email: str
The email to send from (matching
GMAIL_API_KEY
)
- configs.subject: str
The subject that the notification email should have
- class canvas_steps.enrollment.PingNewEnrollment
A propagate step to ping a user when new enrollment is detected.
This step uses Gmail to send an email to a configured recipient, informing them that new enrollment in the course has occurred.
Supported record types:
StudentRecord
Uses metadata:
new_netids
- configs.send_email: str
The email to send from (matching
GMAIL_API_KEY
)
- configs.recv_email: str
The email to send the notification to
- configs.subject: str
The subject that the notification email should have
- class github_steps.add_to_group_repos.AddToGroupRepos
A propagate step to give students permission to their group repos.
This step manages access to group repos through team membership to the corresponding GitHub team. Users are added to the team if they don’t already have access. Additionally, users are removed from their old teams, to prevent them from having access to old groups.
Supported record types:
StudentRecord
Uses metadata:
old_groups
- configs.name_format: str
The format to use for naming GitHub teams. Instances of
<num>
will be replaced with the group’s number.
- configs.num_places: int
The minimum number of places to represent the group’s number with (filling with zeros as necessary). For example, if set to 2, Group 6 would have their number formatted as
06
in their team name.
- class github_steps.add_to_personal_repos.AddToPersonalRepos
A propagate step to give students permission to their personal repos.
This step checks for students that have a personal repo (indicated by having a personal repo name), but don’t currently have access, and provides them access.
Supported record types:
StudentRecord
- class github_steps.create_group_repos.CreateGroupRepos
A propagate step to create any needed group repos.
This step checks for records that have a group number but no repo yet, and creates the appropriate repos with a README file. Additionally, a GitHub team is created with the same name, and is given access to the repo. Students are not yet added to the team.
Supported record types:
StudentRecord
- configs.name_format: str
The format to use for naming GitHub teams. Instances of
<num>
will be replaced with the group’s number.
- configs.num_places: int
The minimum number of places to represent the group’s number with (filling with zeros as necessary). For example, if set to 2, Group 6 would have their number formatted as
06
in their team name.
- configs.readme_path: str
The path to the local README file, to include in the repo. Instances of
<repo_name>
will be replaced appropriately.
- configs.readme_commit_msg: str
The commit message to use when adding the README
- configs.create_upstream: bool
Whether to create a branch of the repo named
upstream
- configs.staff_team: str
The name of the staff team in the GitHub organization. The team will be given access to all created repos.
- configs.staff_permissions: str
The permissions to give the staff team in all created repos (any of
pull
,triage
,push
,maintain
, oradmin
)
- class github_steps.create_personal_repos.CreatePersonalRepos
A propagate step to create any needed personal repos.
This step checks for records that don’t have a repo corresponding to their NetID, and creates a repo for them.
Supported record types:
StudentRecord
- configs.name_format: str
The format to use for naming GitHub teams. Instances of
<netid>
will be replaced with the student’s NetID.
- configs.readme_path: str
The path to the local README file, to include in the repo. Instances of
<repo_name>
will be replaced appropriately.
- configs.readme_commit_msg: str
The commit message to use when adding the README
- configs.create_upstream: bool
Whether to create a branch of the repo named
upstream
- configs.staff_team: str
The name of the staff team in the GitHub organization. The team will be given access to all created repos.
- configs.staff_permissions: str
The permissions to give the staff team in all created repos (any of
pull
,triage
,push
,maintain
, oradmin
)
- class github_steps.invite_students.InviteStudents
Invite students to join the GitHub organization.
This step checks for students that have a valid GitHub username, and invites them to join the GitHub organization.
Supported record types:
StudentRecord
- configs.student_team: str
The name of the student team on GitHub. All students will be invited to join this team.
- class github_steps.remove_unenrolled.RemoveUnenrolled
A propagate step to remove unenrolled users from GitHub.
This step checks for records that have been sent an invite but are no longer enrolled, and removes them from GitHub.
Supported record types:
StudentRecord
- configs.staff_team: str
The name of the staff team on GitHub, to sanity-check that we never remove a staff member
- class github_steps.tag_repo.RepoTagger
A propagate step to tag a specific lab submission.
This step is generated for a specific lab submission and repo type (
personal
orgroup
), and will tag repos of the specified type with the given tag.Supported record types:
TagRecords
Generating
RepoTagger
sRepoTagger
s are unlike other steps in that they are not statically defined. Instead, a dynamic type is created usingget_tagger()
to tag a specific repo type for a specific lab submission. Seeget_tagger()
for more details on how to generateRepoTagger
s- configs.tag_name: str
The tag name that will be used to tag the repos
- configs.deadline: datetime.datetime
The deadline for the lab. Repos will be tagged when this step is run on or after the deadline.
- class github_steps.update_group_repo_descr.UpdateGroupRepoDescr
A propagate step to update group repo descriptions.
This step checks the current membership of each repository, and updates the description if it doesn’t match the current membership. This makes sure that repositories always reflect the most up-to-date group membership.
Supported record types:
StudentRecord
- configs.repo_regex: str
The regex to identify repos to modify. Only repositories with names matching the regex will be modified. Use single quotes in the YAML configuration file to specify.
- class utils.basic_steps.BasicPropagateStep
A basic flow propagate step to log the sum of all records.
Supported record types:
int
- class utils.ping_invalid_username.PingInvalidUsername
Ping users who submitted an invalid username.
This step finds the records that submitted an invalid GitHub username, and emails them informing them of such.
Supported record types:
StudentRecord
- configs.start_date: datetime.datetime
The date when email notifications should start (none will be sent before this date)
- configs.email_gap: int
The number of days to wait between notifications.
- configs.email_template: str
The path to a template email (in the form of a text file). Instances of
<first_name>
,<last_name>
, and<username>
will be replaced appropriately for each notification.
- configs.send_email: str
The email to send from (matching
GMAIL_API_KEY
)
- configs.subject: str
The subject that the notification email should have
- class utils.ping_no_accept.PingNoAccept
Ping users who haven’t accepted their GitHub invitation.
This step finds records that have a pending invitation (that they haven’t accepted), and emails them informing them of such.
Supported record types:
StudentRecord
- configs.start_date: datetime.datetime
The date when email notifications should start (none will be sent before this date)
- configs.email_gap: int
The number of days to wait between notifications.
(Note that this gap is also adhered to from when the invitation was initially sent).
- configs.email_template: str
The path to a template email (in the form of a text file). Instances of
<first_name>
,<last_name>
, and<username>
will be replaced appropriately for each notification.
- configs.send_email: str
The email to send from (matching
GMAIL_API_KEY
)
- configs.subject: str
The subject that the notification email should have
- class utils.ping_no_username.PingNoUsername
Ping users who haven’t submitted a username.
This step finds records that have no GitHub username (a.k.a. they haven’t submitted one yet), and emails them informing them of such.
Supported record types:
StudentRecord
- configs.start_date: datetime.datetime
The date when email notifications should start (none will be sent before this date)
- configs.email_gap: int
The number of days to wait between notifications.
- configs.email_template: str
The path to a template email (in the form of a text file). Instances of
<first_name>
and<last_name>
will be replaced appropriately for each notification.
- configs.send_email: str
The email to send from (matching
GMAIL_API_KEY
)
- configs.subject: str
The subject that the notification email should have