diff --git a/docs/_data/navigation.yml b/docs/_data/navigation.yml index 096c1d83..a9ccbd0e 100644 --- a/docs/_data/navigation.yml +++ b/docs/_data/navigation.yml @@ -43,6 +43,8 @@ url: "/housekeeping-git-requests" - title: "API Requests" url: "/housekeeping-api-requests" + - title: "Repository Location" + url: "/housekeeping-repo-personal-non-owner-push" - title: "Forks" url: "/housekeeping-forks" - title: "Recommendations" diff --git a/docs/demo-data/repositories-personal-non-owner-push-detailed.tsv b/docs/demo-data/repositories-personal-non-owner-push-detailed.tsv new file mode 100644 index 00000000..2ad0f7e1 --- /dev/null +++ b/docs/demo-data/repositories-personal-non-owner-push-detailed.tsv @@ -0,0 +1,3 @@ +repository +alice/something +bob/else diff --git a/docs/demo-data/repositories-personal-non-owner-push.tsv b/docs/demo-data/repositories-personal-non-owner-push.tsv new file mode 100644 index 00000000..a9447e43 --- /dev/null +++ b/docs/demo-data/repositories-personal-non-owner-push.tsv @@ -0,0 +1,4 @@ +date personal repositories with nonowner pushes +2018-01-25 98 +2018-01-24 108 +2018-01-23 110 diff --git a/docs/housekeeping-repo-personal-non-owner-push.html b/docs/housekeeping-repo-personal-non-owner-push.html new file mode 100644 index 00000000..11c9709a --- /dev/null +++ b/docs/housekeeping-repo-personal-non-owner-push.html @@ -0,0 +1,24 @@ +--- +layout: default +title: Forks +permalink: /housekeeping-repo-personal-non-owner-push +--- + +
+

Personal Repositories with Nonowner Pushes in the Last 4 Weeks

+ +
+

+ Repositories in user accounts should only be pushed to by their owners as these repositories might become unavailable or deleted if the owner leaves the company. +

+

Repositories, in which people actively collaborate, should be transferred to an organization account. +

+
+
+ +
+
+
diff --git a/updater/reports/ReportReposPersonalNonOwnerPush.py b/updater/reports/ReportReposPersonalNonOwnerPush.py new file mode 100644 index 00000000..3fe2c135 --- /dev/null +++ b/updater/reports/ReportReposPersonalNonOwnerPush.py @@ -0,0 +1,38 @@ +from .ReportDaily import * + +# Find personal repositories that non-owners are pushing to. +# These repositories should be moved into organizations. +# Only look at active users (not suspended!) and only look at pushes +# of the last 4 weeks. +class ReportReposPersonalNonOwnerPush(ReportDaily): + def name(self): + return "repositories-personal-non-owner-push" + + def updateDailyData(self): + self.detailedHeader, self.detailedData = self.parseData(self.executeQuery(self.query())) + if len(self.data) == 0: + self.header = ["date", "personal repositories with nonowner pushes"] + self.data.append([str(self.yesterday()), len(self.detailedData)]) + self.truncateData(self.timeRangeTotal()) + self.sortDataByDate() + + def query(self): + fourWeeksAgo = self.daysAgo(28) + query = ''' + SELECT + CONCAT(users.login, "/", repositories.name) as "repository" + FROM + repositories + JOIN users ON repositories.owner_id = users.id + JOIN pushes ON pushes.repository_id = repositories.id + WHERE + users.type = "user" + AND users.suspended_at IS NULL + AND CAST(pushes.created_at AS DATE) BETWEEN "''' + str(fourWeeksAgo) + '''" AND "''' + str(self.yesterday()) + '''" + AND pushes.pusher_id != users.id + GROUP BY + repositories.id + ORDER BY + 1 + ''' + return query diff --git a/updater/update-stats.py b/updater/update-stats.py index 1b1c65df..fe637d4f 100755 --- a/updater/update-stats.py +++ b/updater/update-stats.py @@ -23,6 +23,7 @@ from reports.ReportPRUsage import * from reports.ReportRepoActivity import * from reports.ReportRepositoryHistory import * +from reports.ReportReposPersonalNonOwnerPush import * from reports.ReportTeamsTotal import * from reports.ReportTokenlessAuth import * from reports.ReportUsers import * @@ -93,6 +94,7 @@ def main(): ReportPRUsage(configuration, dataDirectory, metaStats).update() ReportRepoActivity(configuration, dataDirectory, metaStats).update() ReportRepositoryHistory(configuration, dataDirectory, metaStats).update() + ReportReposPersonalNonOwnerPush(configuration, dataDirectory, metaStats).update() ReportTeamsTotal(configuration, dataDirectory, metaStats).update() ReportTokenlessAuth(configuration, dataDirectory, metaStats).update() ReportUsers(configuration, dataDirectory, metaStats).update()