-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathbot.ts
More file actions
208 lines (185 loc) · 5.86 KB
/
bot.ts
File metadata and controls
208 lines (185 loc) · 5.86 KB
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
import { existsSync } from "node:fs";
import {
parse as parseToml,
stringify as stringifyToml,
} from "jsr:@std/toml@1.0.2";
import {
format as formatSemVer,
increment as incrementSemVer,
parse as parseSemVer,
} from "jsr:@std/semver@1.0.4";
import * as cases from "jsr:@luca/cases@1";
import {
correctRepoInfo,
createWorkDir,
fetchPrAndSetupBranch,
fetchRepo,
getExistingPR,
getGitHubUsername,
getReposWithIssueN,
openPR,
switchDirTemp,
updatePr,
} from "./utils.ts";
const ISSUE_NUMBER = 2104;
if (import.meta.main) {
const repos = await getReposWithIssueN(ISSUE_NUMBER);
const tempDir = createWorkDir();
Deno.chdir(tempDir);
// Get GitHub username
const botUsername = await getGitHubUsername();
console.log(`Using GitHub username: ${botUsername}`);
for (let [index, repo] of repos.entries()) {
console.log(`[${index}] Processing repo: ${JSON.stringify(repo)}`);
// This is neeed to handle repo renaming
// Get the *current* repository name using gh repo view
repo = await correctRepoInfo(repo);
// Check for existing PRs *before* cloning or doing any work
const existingPRBranchName = await getExistingPR(
repo.user,
repo.name,
botUsername,
);
await fetchRepo(repo.repo);
if (existingPRBranchName) {
console.log(
`Found existing PR for ${repo.user}/${repo.name}: updating it...`,
);
await fetchPrAndSetupBranch(
{
repoName: repo.name,
branchName: existingPRBranchName,
botUsername,
},
);
let changes = false;
{
using _ = switchDirTemp(repo.name);
if (_updateExistingPRRemoveJsonConfig()) changes = true;
if (await updateCleanup()) changes = true;
}
if (changes) {
await updatePr({
repoUser: repo.user,
repoName: repo.name,
branchName: existingPRBranchName,
commitMsg: "remvoe extension.json and cleanup",
});
}
} else {
let changed = false;
{
using _ = switchDirTemp(repo.name);
changed = portExtToToml();
}
if (changed) {
await openPR({
repoUser: repo.user,
repoName: repo.name,
botUsername,
commitMsg: "add extension.toml",
prTitle: "Add extension.toml",
prBody:
`This PR adds 'extension.toml' file, converting from the existing 'extension.json' configuration.
See https://github.com/zed-industries/extensions/issues/2104
This change was generated automatically and needs to be manually tested.
Bot script: https://github.com/sigmaSd/botfixzed/blob/master/bot2104.ts`,
});
}
}
// Uncomment to process only the first repo
// break;
}
}
function portExtToToml() {
if (existsSync("extension.toml")) {
console.log("Skipping existing extension.toml");
return false;
}
const jsonConfig = JSON.parse(
Deno.readTextFileSync("extension.json"),
);
jsonConfig.id = cases.kebabCase(jsonConfig.name);
jsonConfig.version = formatSemVer(
incrementSemVer(parseSemVer(jsonConfig.version), "patch"),
);
jsonConfig.schema_version = 1;
let tomlConfig = stringifyToml(jsonConfig);
const maybeRepoConfig = findRepoConfig(Deno.cwd());
if (maybeRepoConfig) {
tomlConfig += `grammar = "${maybeRepoConfig.name}"`;
tomlConfig += `
[grammars.${maybeRepoConfig.name}]
${maybeRepoConfig.content}`;
}
// console.log(tomlConfig);
Deno.writeTextFileSync("extension.toml", tomlConfig);
return true;
}
function findRepoConfig(path: string) {
if (!existsSync(`${path}/grammars`)) return;
for (const entry of Deno.readDirSync(`${path}/grammars`)) {
if (entry.isFile && entry.name.endsWith(".toml")) {
const content = Deno.readTextFileSync(`${path}/grammars/${entry.name}`);
return { name: entry.name.replace(/\.toml$/, ""), content };
}
}
}
// https://github.com/zed-industries/extensions/issues/2104#issuecomment-2707475876
function _updateExistingPRRemoveJsonConfig() {
console.log("Updating PR to remove extension.json");
// Check if extension.json exists
if (!existsSync("extension.json")) {
console.log("extension.json doesn't exist. No need to update PR.");
return false;
}
Deno.removeSync("extension.json");
return true;
}
async function updateCleanup() {
if (!existsSync("extension.toml")) {
return false;
}
// seems like earlier I created a corrupt toml by having
// [grammars] alongside [grammars.matlab]
// the issue we can't even parse it to fix it
// the workaround is simple, string replacement
const tomlFileOld = await Deno.readTextFile("extension.toml");
const tomlConfig = parseToml(
tomlFileOld.replace("[grammars]", "[grammarsDELETE]"),
);
// 1. remove grammar = type
delete tomlConfig.grammar;
// 2. remove [grammar]
delete tomlConfig.grammarsDELETE;
// 3. remove [languages]
delete tomlConfig.languages;
// 4. remove grammars folder
{
try {
await Deno.remove("grammars", { recursive: true });
} catch { /* ignore */ }
}
// Not all repos need this, lets just ignore the gitignore
// 5. setup gitignore
// {
// let gitIgnoreContent = "";
// try {
// gitIgnoreContent = await Deno.readTextFile(".gitignore");
// } catch { /* ignore */ }
// const gitignore = await Deno.open(".gitignore", {
// append: true,
// create: true,
// });
// if (!gitIgnoreContent.includes("grammars")) {
// await gitignore.write(new TextEncoder().encode("grammars\n"));
// }
// if (!gitIgnoreContent.includes("*.wasm")) {
// await gitignore.write(new TextEncoder().encode("*.wasm\n"));
// }
// }
const tomlFileNew = stringifyToml(tomlConfig);
await Deno.writeTextFile("extension.toml", tomlFileNew);
// console.log("new", Deno.readTextFileSync("extension.toml"));
return tomlFileNew !== tomlFileOld;
}