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 with canvas_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, or admin)

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, or admin)

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 or group), and will tag repos of the specified type with the given tag.

Supported record types: TagRecords

Generating RepoTaggers

RepoTaggers are unlike other steps in that they are not statically defined. Instead, a dynamic type is created using get_tagger() to tag a specific repo type for a specific lab submission. See get_tagger() for more details on how to generate RepoTaggers

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