forked from open-vsx/publish-extensions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
upgrade-extensions.js
113 lines (105 loc) · 5.15 KB
/
upgrade-extensions.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
/********************************************************************************
* Copyright (c) 2020 TypeFox and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
********************************************************************************/
// @ts-check
const fs = require('fs');
const https = require('https');
const util = require('util');
const exec = require('./lib/exec');
const readFile = util.promisify(fs.readFile);
const writeFile = util.promisify(fs.writeFile);
const dontUpgrade = [
'alefragnani.Bookmarks', // https://github.com/alefragnani/vscode-bookmarks/issues/315
'alefragnani.project-manager', // https://github.com/alefragnani/vscode-bookmarks/issues/315
'chenglou.rescript-language-server', // .vsix releases are no longer available under https://github.com/rescript-lang/rescript-vscode/releases
];
(async () => {
/**
* @type {{
* extensions: {
* id: string,
* repository: string,
* version?: string,
* checkout?: string,
* location?: string,
* prepublish?: string,
* download?: string
* }[]
* }}
*/
const { extensions } = JSON.parse(await readFile('./extensions.json', 'utf-8'));
const extensionRepositoriesToUpgrade = extensions.filter(e => !dontUpgrade.includes(e.id) && !!e.version && !e.download);
const extensionDownloadsToUpgrade = extensions.filter(e => !dontUpgrade.includes(e.id) && /https:\/\/github.com\/.*\/releases\/download\//.test(e.download));
const extensionsToNotUpgrade = extensions.filter(e => !extensionRepositoriesToUpgrade.concat(extensionDownloadsToUpgrade).map(e => e.id).includes(e.id));
fs.renameSync('./extensions.json', './extensions.json.old');
try {
await writeFile('./extensions.json', JSON.stringify({ extensions: extensionsToNotUpgrade }, null, 2) + '\n', 'utf-8');
for (const extension of extensionRepositoriesToUpgrade) {
let command = 'node add-extension ' + extension.repository;
if (extension.checkout) {
// Since we're upgrading, don't use the currently pinned Git branch, tag, or commit. Use the default Git branch instead.
command += ' --checkout';
}
if (extension.location) {
command += ' --location=' + JSON.stringify(extension.location);
}
if (extension.prepublish) {
command += ' --prepublish=' + JSON.stringify(extension.prepublish);
}
await exec(command);
}
for (const extension of extensionDownloadsToUpgrade) {
// Scrape the latest GitHub releases to check for updates.
const releasesUrl = extension.download.replace(/\/releases\/download\/.*$/, '/releases');
console.log(`Scraping ${releasesUrl} to check for updates...`);
const releases = await get(releasesUrl);
const latest = releases.match(/\/releases\/download\/[-._a-zA-Z0-9\/%]*\.vsix/g).filter(release => !/(nightly|-rc|-alpha|-beta)/.test(release)).shift();
await exec('node add-extension --download=' + (latest ? extension.download.replace(/\/releases\/download\/.*$/, latest) : extension.download));
}
// One last pass to clean up results with a few helpful heuristics.
const { extensions: upgradedExtensions } = JSON.parse(await readFile('./extensions.json', 'utf-8'));
for (const upgradedExtension of upgradedExtensions) {
const originalExtension = extensionRepositoriesToUpgrade.find(extension => extension.id === upgradedExtension.id);
if (!originalExtension) {
// This extension likely wasn't actually upgraded, leave it as is.
continue;
}
if (upgradedExtension.version && upgradedExtension.version !== originalExtension.version && !upgradedExtension.checkout) {
// If "version" was bumped, but we're publishing from the default branch, it's probably better to just unpin the version.
delete upgradedExtension.version;
}
if (upgradedExtension.checkout !== originalExtension.checkout && upgradedExtension.version === originalExtension.version) {
// If "checkout" was modified, but "version" stayed the same, the change of "checkout" is unhelpful. Reset it.
upgradedExtension.checkout = originalExtension.checkout;
}
}
await writeFile('./extensions.json', JSON.stringify({ extensions: upgradedExtensions }, null, 2) + '\n', 'utf-8');
} catch (error) {
console.error(`[FAIL] Could not upgrade extensions.json!`);
console.error(error);
process.exitCode = -1;
fs.renameSync('./extensions.json.old', './extensions.json');
}
})();
function get(url) {
return new Promise((resolve, reject) => {
https.get(url, res => {
if (res.statusCode >= 400) {
reject(new Error(`Couldn't get ${url} - Response status: ${res.statusCode}`));
return;
}
let body = '';
res.on('data', chunk => { body += chunk; });
res.on('error', error => { reject(error); });
res.on('end', () => { resolve(body); });
}).on('error', error => {
reject(error);
});
});
}