PullTeamsFromGithubJob.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.HashMap;
16
import java.util.List;
17
import java.util.Map;
18
import java.util.Optional;
19
import java.util.concurrent.atomic.AtomicBoolean;
20
import lombok.Builder;
21
22
@Builder
23
public class PullTeamsFromGithubJob implements JobContextConsumer {
24
  Long courseId;
25
  CourseRepository courseRepository;
26
  TeamRepository teamRepository;
27
  TeamMemberRepository teamMemberRepository;
28
  GithubTeamService githubTeamService;
29
30
  @Override
31
  public void accept(JobContext ctx) throws Exception {
32
    ctx.log(String.format("Starting pull teams from GitHub job for course ID: %s", courseId));
33
34
    Optional<Course> courseOpt = courseRepository.findById(courseId);
35 1 1. accept : negated conditional → KILLED
    if (courseOpt.isEmpty()) {
36
      ctx.log(String.format("ERROR: Course with ID %s not found", courseId));
37
      return;
38
    }
39
    Course course = courseOpt.get();
40
    ctx.log(
41
        String.format(
42
            "Processing course: %s (org: %s)", course.getCourseName(), course.getOrgName()));
43
44 2 1. accept : negated conditional → KILLED
2. accept : negated conditional → KILLED
    if (course.getOrgName() == null || course.getInstallationId() == null) {
45
      ctx.log("ERROR: Course has no linked GitHub organization");
46
      return;
47
    }
48
49
    List<GithubTeamInfo> githubTeams;
50
    try {
51
      githubTeams = githubTeamService.getAllTeams(course);
52
    } catch (Exception e) {
53
      ctx.log(String.format("ERROR: Failed to pull teams from GitHub: %s", e.getMessage()));
54
      return;
55
    }
56
57
    Map<Integer, Team> localByGithubId = new HashMap<>();
58
    Map<String, Team> localByName = new HashMap<>();
59
    Map<String, RosterStudent> localStudentsByGithubLogin = new HashMap<>();
60
    for (Team localTeam : teamRepository.findByCourseId(courseId)) {
61 1 1. accept : negated conditional → KILLED
      if (localTeam.getGithubTeamId() != null) {
62
        localByGithubId.put(localTeam.getGithubTeamId(), localTeam);
63
      }
64
      localByName.put(localTeam.getName(), localTeam);
65
    }
66 1 1. accept : negated conditional → KILLED
    if (course.getRosterStudents() != null) {
67
      for (RosterStudent student : course.getRosterStudents()) {
68 1 1. accept : negated conditional → KILLED
        if (student.getGithubLogin() != null) {
69
          localStudentsByGithubLogin.put(student.getGithubLogin(), student);
70
        }
71
      }
72
    }
73
74
    int created = 0;
75
    int updated = 0;
76
    int unchanged = 0;
77
78
    for (GithubTeamInfo githubTeam : githubTeams) {
79
      Team localTeam = localByGithubId.get(githubTeam.id());
80 1 1. accept : negated conditional → KILLED
      if (localTeam == null) {
81
        localTeam = localByName.get(githubTeam.name());
82
      }
83
84
      boolean teamCreated = false;
85 1 1. accept : negated conditional → KILLED
      if (localTeam == null) {
86
        Team newTeam =
87
            Team.builder()
88
                .name(githubTeam.name())
89
                .course(course)
90
                .githubTeamId(githubTeam.id())
91
                .githubTeamSlug(githubTeam.slug())
92
                .build();
93
        teamRepository.save(newTeam);
94
        localByGithubId.put(githubTeam.id(), newTeam);
95
        localByName.put(githubTeam.name(), newTeam);
96 1 1. accept : Changed increment from 1 to -1 → KILLED
        created++;
97
        ctx.log(
98
            String.format(
99
                "Created local team '%s' with GitHub team ID: %d",
100
                githubTeam.name(), githubTeam.id()));
101
        localTeam = newTeam;
102
        teamCreated = true;
103
      }
104
105
      AtomicBoolean teamUnchanged = new AtomicBoolean(true);
106 1 1. accept : negated conditional → KILLED
      if (!teamCreated) {
107 1 1. accept : negated conditional → KILLED
        if (!githubTeam.name().equals(localTeam.getName())) {
108
          localByName.remove(localTeam.getName());
109 1 1. accept : removed call to edu/ucsb/cs156/frontiers/entities/Team::setName → KILLED
          localTeam.setName(githubTeam.name());
110 1 1. accept : removed call to java/util/concurrent/atomic/AtomicBoolean::set → KILLED
          teamUnchanged.set(false);
111
        }
112 1 1. accept : negated conditional → KILLED
        if (!githubTeam.id().equals(localTeam.getGithubTeamId())) {
113 1 1. accept : negated conditional → KILLED
          if (localTeam.getGithubTeamId() != null) {
114
            localByGithubId.remove(localTeam.getGithubTeamId());
115
          }
116 1 1. accept : removed call to edu/ucsb/cs156/frontiers/entities/Team::setGithubTeamId → KILLED
          localTeam.setGithubTeamId(githubTeam.id());
117 1 1. accept : removed call to java/util/concurrent/atomic/AtomicBoolean::set → KILLED
          teamUnchanged.set(false);
118
        }
119 1 1. accept : negated conditional → KILLED
        if (localTeam.getGithubTeamSlug() == null
120 1 1. accept : negated conditional → KILLED
            || !githubTeam.slug().equals(localTeam.getGithubTeamSlug())) {
121 1 1. accept : removed call to edu/ucsb/cs156/frontiers/entities/Team::setGithubTeamSlug → KILLED
          localTeam.setGithubTeamSlug(githubTeam.slug());
122 1 1. accept : removed call to java/util/concurrent/atomic/AtomicBoolean::set → KILLED
          teamUnchanged.set(false);
123
        }
124
125 1 1. accept : negated conditional → KILLED
        if (!teamUnchanged.get()) {
126
          teamRepository.save(localTeam);
127
          ctx.log(
128
              String.format(
129
                  "Updated local team '%s' with GitHub team ID: %d",
130
                  localTeam.getName(), githubTeam.id()));
131
        }
132
      }
133
134
      localByGithubId.put(githubTeam.id(), localTeam);
135
      localByName.put(localTeam.getName(), localTeam);
136
137 1 1. accept : negated conditional → KILLED
      if (!localStudentsByGithubLogin.isEmpty()) {
138
        Map<String, TeamStatus> githubMemberships =
139
            githubTeamService.getTeamMemberships(githubTeam.slug(), course);
140
        Team currentTeam = localTeam;
141 1 1. accept : removed call to java/util/Map::forEach → KILLED
        githubMemberships.forEach(
142
            (githubLogin, membershipStatus) -> {
143
              RosterStudent student = localStudentsByGithubLogin.get(githubLogin);
144 1 1. lambda$accept$0 : negated conditional → KILLED
              if (student == null) {
145
                return;
146
              }
147
148
              Optional<TeamMember> existingTeamMember =
149
                  teamMemberRepository.findByTeamAndRosterStudent(currentTeam, student);
150 1 1. lambda$accept$0 : negated conditional → KILLED
              if (existingTeamMember.isPresent()) {
151
                TeamMember teamMember = existingTeamMember.get();
152 1 1. lambda$accept$0 : negated conditional → KILLED
                if (teamMember.getTeamStatus() != membershipStatus) {
153 1 1. lambda$accept$0 : removed call to edu/ucsb/cs156/frontiers/entities/TeamMember::setTeamStatus → KILLED
                  teamMember.setTeamStatus(membershipStatus);
154
                  teamMemberRepository.save(teamMember);
155 1 1. lambda$accept$0 : removed call to java/util/concurrent/atomic/AtomicBoolean::set → KILLED
                  teamUnchanged.set(false);
156
                  ctx.log(
157
                      String.format(
158
                          "Updated team member '%s' in team '%s' with status %s",
159
                          githubLogin, currentTeam.getName(), membershipStatus));
160
                }
161
              } else {
162
                TeamMember newTeamMember =
163
                    TeamMember.builder()
164
                        .team(currentTeam)
165
                        .rosterStudent(student)
166
                        .teamStatus(membershipStatus)
167
                        .build();
168
                teamMemberRepository.save(newTeamMember);
169 1 1. lambda$accept$0 : removed call to java/util/concurrent/atomic/AtomicBoolean::set → KILLED
                teamUnchanged.set(false);
170
                ctx.log(
171
                    String.format(
172
                        "Created team member '%s' in team '%s' with status %s",
173
                        githubLogin, currentTeam.getName(), membershipStatus));
174
              }
175
            });
176
      }
177
178 1 1. accept : negated conditional → KILLED
      if (!teamCreated) {
179 1 1. accept : negated conditional → KILLED
        if (teamUnchanged.get()) {
180 1 1. accept : Changed increment from 1 to -1 → KILLED
          unchanged++;
181
        } else {
182 1 1. accept : Changed increment from 1 to -1 → KILLED
          updated++;
183
        }
184
      }
185
    }
186
187
    ctx.log(
188
        String.format(
189
            "Completed pull teams from GitHub job for course ID: %s (GitHub teams: %d, created: %d, updated: %d, unchanged: %d)",
190
            courseId, githubTeams.size(), created, updated, unchanged));
191
  }
192
}

Mutations

35

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

44

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

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

61

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

66

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

68

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

80

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

85

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

96

1.1
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests]/[method:testAccept_RemovesOldGithubIdMappingWhenMatchingByName()]
Changed increment from 1 to -1 → KILLED

106

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

107

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

109

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

110

1.1
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests]/[method:testAccept_UpdatesExistingTeamWhenOnlyNameChanges()]
removed call to java/util/concurrent/atomic/AtomicBoolean::set → KILLED

112

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

113

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

116

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

117

1.1
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests]/[method:testAccept_UpdatesExistingTeamWhenOnlyGithubIdChanges()]
removed call to java/util/concurrent/atomic/AtomicBoolean::set → KILLED

119

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

120

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

121

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

122

1.1
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests]/[method:testAccept_UpdatesExistingTeamWhenOnlySlugChanges()]
removed call to java/util/concurrent/atomic/AtomicBoolean::set → KILLED

125

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

137

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

141

1.1
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests]/[method:testAccept_DoesNotUpdateOrLogWhenMembershipStatusIsUnchanged()]
removed call to java/util/Map::forEach → KILLED

144

1.1
Location : lambda$accept$0
Killed by : edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests]/[method:testAccept_DoesNotUpdateOrLogWhenMembershipStatusIsUnchanged()]
negated conditional → KILLED

150

1.1
Location : lambda$accept$0
Killed by : edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests]/[method:testAccept_DoesNotUpdateOrLogWhenMembershipStatusIsUnchanged()]
negated conditional → KILLED

152

1.1
Location : lambda$accept$0
Killed by : edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests]/[method:testAccept_DoesNotUpdateOrLogWhenMembershipStatusIsUnchanged()]
negated conditional → KILLED

153

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

155

1.1
Location : lambda$accept$0
Killed by : edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests]/[method:testAccept_CountsTeamUpdatedWhenOnlyMembershipUpdateOccurs()]
removed call to java/util/concurrent/atomic/AtomicBoolean::set → KILLED

169

1.1
Location : lambda$accept$0
Killed by : edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests]/[method:testAccept_CountsTeamUpdatedWhenOnlyMembershipCreateOccurs()]
removed call to java/util/concurrent/atomic/AtomicBoolean::set → KILLED

178

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

179

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

180

1.1
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests]/[method:testAccept_DoesNotUpdateOrLogWhenMembershipStatusIsUnchanged()]
Changed increment from 1 to -1 → KILLED

182

1.1
Location : accept
Killed by : edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.jobs.PullTeamsFromGithubJobTests]/[method:testAccept_UpdatesExistingTeamWhenOnlySlugChanges()]
Changed increment from 1 to -1 → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0