This repository has been archived by the owner on Feb 27, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy patharchive.js
147 lines (124 loc) · 3.85 KB
/
archive.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
const moment = require("moment");
const octokit = require("../lib/client");
const delay = require("../lib/delay");
const { getRepos } = require("../lib/repos");
// https://developer.github.com/v3/#schema
const parseGitHubTimestamp = (str) => moment(str, moment.ISO_8601);
const getLatestEvent = async (repo) => {
const eventResponse = await octokit.activity.listRepoEvents({
owner: repo.owner.login,
repo: repo.name,
});
// filter out certain events
// https://developer.github.com/v3/activity/events/types/
const IGNORED_EVENTS = ["ForkEvent", "StarEvent", "WatchEvent"];
const events = eventResponse.data.filter(
(event) => !IGNORED_EVENTS.includes(event.type)
);
return events[0];
};
const hasMaintainedTopic = async ({ name: repo, owner: { login: owner }}) => {
const { data: { names }} = await octokit.repos.getAllTopics({ owner, repo });
return names.map(n => n.toLowerCase()).includes("maintained");
}
const attrAfter = (dateStr, cutoff) => {
const date = parseGitHubTimestamp(dateStr);
return date.isAfter(cutoff);
};
const updatedSince = async (repo, cutoff) => {
if (attrAfter(repo.updated_at, cutoff)) {
return true;
}
if (attrAfter(repo.pushed_at, cutoff)) {
return true;
}
const latestEvent = await getLatestEvent(repo);
if (latestEvent) {
if (attrAfter(latestEvent.created_at, cutoff)) {
return true;
}
}
return false;
};
const hasDeprecationText = (str) =>
/\b(DEPRECATED|NO(T| LONGER) SUPPORTED)\b/i.test(str);
const shouldBeArchived = async (repo, cutoff) => {
// always archive "DEPRECATED" repositories
const description = repo.description || "";
if (hasDeprecationText(description)) {
return true;
}
// If the repo has a "MAINTAINED" topic, skip it.
const maintained = await hasMaintainedTopic(repo);
if(maintained) {
return false;
}
// Don't archive cloud.gov repos, these are maintained
if(repo.owner.login === 'cloud-gov'){
return false;
}
// if anything has happened with the repository since the cutoff, skip it
const recentlyUpdated = await updatedSince(repo, cutoff);
return !recentlyUpdated;
};
const archiveRepo = (repo) => {
return octokit.repos.update({
owner: repo.owner.login,
repo: repo.name,
archived: true,
});
};
const archiveIfStale = async (repo, cutoff, apply) => {
const archive = await shouldBeArchived(repo, cutoff);
if (archive) {
if (apply) {
await archiveRepo(repo);
console.log(`Archived ${repo.html_url}`);
// https://developer.github.com/v3/guides/best-practices-for-integrators/#dealing-with-abuse-rate-limits
await delay(1000);
} else {
console.log(`Would archive ${repo.html_url}`);
}
return true;
}
return false;
};
const processRepos = async (repos, cutoff, apply) => {
let promises = [];
for await (const repo of repos) {
// don't wait for this to happen
const promise = archiveIfStale(repo, cutoff, apply);
promises.push(promise);
}
// wait until all archiving has completed
const results = await Promise.all(promises);
const numReposConsidered = results.length;
// https://stackoverflow.com/a/42317235/358804
const numReposArchived = results.filter(Boolean).length;
let msg = `Out of ${numReposConsidered} repositories considered, ${numReposArchived} `;
if (!apply) {
msg += "would be ";
}
msg += "archived.";
console.log(msg);
};
const archiveStaleRepos = async (cutoff, opts) => {
if (!opts.apply) {
process.stdout.write("DRY RUN: ");
}
if (opts.org) {
console.log(`Archiving stale repositories for ${opts.org}...`);
} else {
console.log("Archiving stale repositories...");
}
const repos = getRepos(opts.org);
await processRepos(repos, cutoff, opts.apply);
console.log("Done.");
};
module.exports = {
getLatestEvent,
attrAfter,
hasDeprecationText,
hasMaintainedTopic,
archiveStaleRepos,
};