PushTeamsToGithubJob.java

1
package edu.ucsb.cs156.frontiers.jobs;
2
3
import edu.ucsb.cs156.frontiers.entities.Course;
4
import edu.ucsb.cs156.frontiers.entities.RosterStudent;
5
import edu.ucsb.cs156.frontiers.entities.Team;
6
import edu.ucsb.cs156.frontiers.entities.TeamMember;
7
import edu.ucsb.cs156.frontiers.enums.TeamStatus;
8
import edu.ucsb.cs156.frontiers.repositories.CourseRepository;
9
import edu.ucsb.cs156.frontiers.repositories.TeamMemberRepository;
10
import edu.ucsb.cs156.frontiers.repositories.TeamRepository;
11
import edu.ucsb.cs156.frontiers.services.GithubTeamService;
12
import edu.ucsb.cs156.frontiers.services.GithubTeamService.GithubTeamInfo;
13
import edu.ucsb.cs156.frontiers.services.jobs.JobContext;
14
import edu.ucsb.cs156.frontiers.services.jobs.JobContextConsumer;
15
import java.util.Objects;
16
import java.util.Optional;
17
import lombok.Builder;
18
19
@Builder
20
public class PushTeamsToGithubJob implements JobContextConsumer {
21
  Long courseId;
22
  CourseRepository courseRepository;
23
  TeamRepository teamRepository;
24
  TeamMemberRepository teamMemberRepository;
25
  GithubTeamService githubTeamService;
26
27
  @Override
28
  public Course getCourse() {
29
    Optional<Course> courseOpt = courseRepository.findById(courseId);
30 1 1. getCourse : replaced return value with null for edu/ucsb/cs156/frontiers/jobs/PushTeamsToGithubJob::getCourse → KILLED
    return courseOpt.orElse(null);
31
  }
32
33
  @Override
34
  public void accept(JobContext ctx) throws Exception {
35
    ctx.log("Starting push teams to GitHub job for course ID: " + courseId);
36
37
    // Get the course
38
    Optional<Course> courseOpt = courseRepository.findById(courseId);
39 1 1. accept : negated conditional → KILLED
    if (courseOpt.isEmpty()) {
40
      ctx.log("ERROR: Course with ID " + courseId + " not found");
41
      return;
42
    }
43
    Course course = courseOpt.get();
44
    ctx.log("Processing course: " + course.getCourseName() + " (org: " + course.getOrgName() + ")");
45
46 2 1. accept : negated conditional → KILLED
2. accept : negated conditional → KILLED
    if (course.getOrgName() == null || course.getInstallationId() == null) {
47
      ctx.log("ERROR: Course has no linked GitHub organization");
48
      return;
49
    }
50
51
    // Get the organization id
52
53
    Integer orgId = null;
54
    try {
55
      orgId = githubTeamService.getOrgId(course.getOrgName(), course);
56
    } catch (Exception e) {
57
      throw new IllegalStateException(
58
          "Failed to get organization ID for org: " + course.getOrgName() + " - " + e.getMessage(),
59
          e);
60
    }
61
62
    // Get all teams for this course
63
    Iterable<Team> teams = teamRepository.findByCourseId(courseId);
64
65
    // First pass: Create teams on GitHub and update githubTeamId
66
    for (Team team : teams) {
67
      ctx.log("Processing team: " + team.getName());
68
      try {
69
        GithubTeamInfo githubTeamInfo = githubTeamService.createOrGetTeamInfo(team, course);
70 1 1. accept : negated conditional → KILLED
        if (!githubTeamInfo.id().equals(team.getGithubTeamId())
71 1 1. accept : negated conditional → KILLED
            || !Objects.equals(githubTeamInfo.slug(), team.getGithubTeamSlug())) {
72 1 1. accept : removed call to edu/ucsb/cs156/frontiers/entities/Team::setGithubTeamId → KILLED
          team.setGithubTeamId(githubTeamInfo.id());
73 1 1. accept : removed call to edu/ucsb/cs156/frontiers/entities/Team::setGithubTeamSlug → KILLED
          team.setGithubTeamSlug(githubTeamInfo.slug());
74
          teamRepository.save(team);
75
          ctx.log(
76
              "Updated team '" + team.getName() + "' with GitHub team ID: " + githubTeamInfo.id());
77
        } else {
78
          ctx.log(
79
              "Team '"
80
                  + team.getName()
81
                  + "' already has correct GitHub team ID: "
82
                  + githubTeamInfo.id());
83
        }
84
      } catch (Exception e) {
85
        ctx.log("ERROR: Failed to create/get team '" + team.getName() + "': " + e.getMessage());
86
      }
87
    }
88
89
    // Second pass: Process team members
90
    for (Team team : teams) {
91 1 1. accept : negated conditional → KILLED
      if (team.getGithubTeamId() == null) {
92
        ctx.log("Skipping team members for '" + team.getName() + "' - no GitHub team ID");
93
        continue;
94
      }
95
96
      ctx.log("Processing members for team: " + team.getName());
97
      for (TeamMember teamMember : team.getTeamMembers()) {
98
        RosterStudent student = teamMember.getRosterStudent();
99 1 1. accept : negated conditional → KILLED
        if (student.getGithubLogin() == null) {
100
          // Update status to NO_GITHUB_ID
101 1 1. accept : removed call to edu/ucsb/cs156/frontiers/entities/TeamMember::setTeamStatus → KILLED
          teamMember.setTeamStatus(TeamStatus.NO_GITHUB_ID);
102
          teamMemberRepository.save(teamMember);
103
          ctx.log(
104
              "Student " + student.getEmail() + " has no GitHub login - marked as NO_GITHUB_ID");
105
          continue;
106
        }
107
108
        try {
109
          // Check current status
110
          TeamStatus currentStatus =
111
              githubTeamService.getTeamMembershipStatus(
112
                  student.getGithubLogin(), team.getGithubTeamId(), course, orgId);
113
114 2 1. accept : negated conditional → KILLED
2. accept : negated conditional → KILLED
          if (currentStatus == TeamStatus.TEAM_MEMBER
115
              || currentStatus == TeamStatus.TEAM_MAINTAINER) {
116
            // Already a member, just update the status
117 1 1. accept : removed call to edu/ucsb/cs156/frontiers/entities/TeamMember::setTeamStatus → KILLED
            teamMember.setTeamStatus(currentStatus);
118
            teamMemberRepository.save(teamMember);
119
            ctx.log(
120
                "Student " + student.getGithubLogin() + " already has status: " + currentStatus);
121
          } else {
122
            // Add as member
123
            TeamStatus newStatus =
124
                githubTeamService.addMemberToGithubTeam(
125
                    student.getGithubLogin(), team.getGithubTeamId(), "member", course, orgId);
126 1 1. accept : removed call to edu/ucsb/cs156/frontiers/entities/TeamMember::setTeamStatus → KILLED
            teamMember.setTeamStatus(newStatus);
127
            teamMemberRepository.save(teamMember);
128
            ctx.log(
129
                "Added student " + student.getGithubLogin() + " to team with status: " + newStatus);
130
          }
131
        } catch (Exception e) {
132
          ctx.log(
133
              "ERROR: Failed to process team member "
134
                  + student.getGithubLogin()
135
                  + " for team '"
136
                  + team.getName()
137
                  + "': "
138
                  + e.getMessage());
139 1 1. accept : removed call to edu/ucsb/cs156/frontiers/entities/TeamMember::setTeamStatus → KILLED
          teamMember.setTeamStatus(TeamStatus.NOT_ORG_MEMBER);
140
          teamMemberRepository.save(teamMember);
141
        }
142
      }
143
    }
144
145
    ctx.log("Completed push teams to GitHub job for course ID: " + courseId);
146
  }
147
}

Mutations

30

1.1
Location : getCourse
Killed by : edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests]/[method:test_getCourse_returnsCourse_whenFound()]
replaced return value with null for edu/ucsb/cs156/frontiers/jobs/PushTeamsToGithubJob::getCourse → KILLED

39

1.1
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests]/[method:testAccept_CourseNotFound()]
negated conditional → KILLED

46

1.1
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests]/[method:test_Accept_GetOrgIdFailure()]
negated conditional → KILLED

2.2
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests]/[method:testAccept_CourseWithOrgNameButNoInstallationId()]
negated conditional → KILLED

70

1.1
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests]/[method:testAccept_UpdatesTeamWhenOnlyGithubTeamIdDiffers()]
negated conditional → KILLED

71

1.1
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests]/[method:testAccept_UpdatesTeamWhenOnlyGithubTeamSlugDiffers()]
negated conditional → KILLED

72

1.1
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests]/[method:testAccept_UpdatesTeamWhenOnlyGithubTeamIdDiffers()]
removed call to edu/ucsb/cs156/frontiers/entities/Team::setGithubTeamId → KILLED

73

1.1
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests]/[method:testAccept_UpdatesTeamWhenOnlyGithubTeamSlugDiffers()]
removed call to edu/ucsb/cs156/frontiers/entities/Team::setGithubTeamSlug → KILLED

91

1.1
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests]/[method:testAccept_TeamWithNoGithubTeamId()]
negated conditional → KILLED

99

1.1
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests]/[method:testAccept_ExistingTeamMember()]
negated conditional → KILLED

101

1.1
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests]/[method:testAccept_SuccessfulTeamCreationAndMemberProcessing()]
removed call to edu/ucsb/cs156/frontiers/entities/TeamMember::setTeamStatus → KILLED

114

1.1
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests]/[method:testAccept_ExistingTeamMember()]
negated conditional → KILLED

2.2
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests]/[method:testAccept_ExistingTeamMaintainer()]
negated conditional → KILLED

117

1.1
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests]/[method:testAccept_ExistingTeamMember()]
removed call to edu/ucsb/cs156/frontiers/entities/TeamMember::setTeamStatus → KILLED

126

1.1
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests]/[method:testAccept_SuccessfulTeamCreationAndMemberProcessing()]
removed call to edu/ucsb/cs156/frontiers/entities/TeamMember::setTeamStatus → KILLED

139

1.1
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PushTeamsToGithubJobTests]/[method:testAccept_TeamMemberProcessingFailure()]
removed call to edu/ucsb/cs156/frontiers/entities/TeamMember::setTeamStatus → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0