Skip to content

Commit 4f86b1c

Browse files
authored
Add pylance-version option (#63)
1 parent 545429f commit 4f86b1c

7 files changed

Lines changed: 505 additions & 41 deletions

File tree

‎README.md‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ GitHub action for [pyright](https://github.com/microsoft/pyright). Featuring:
2222
inputs:
2323
# Options for pyright-action
2424
version:
25-
description: 'Version of pyright to run. If not specified, the latest version will be used.'
25+
description: 'Version of pyright to run. If neither version nor pylance-version are specified, the latest version will be used.'
26+
required: false
27+
pylance-version:
28+
description: 'Version of pylance whose pyright version should be run. Can be latest-release, latest-prerelease, or a specific pylance version. Ignored if version option is specified.'
2629
required: false
2730
working-directory:
2831
description: 'Directory to run pyright in. If not specified, the repo root will be used.'
@@ -132,3 +135,23 @@ poetry's python binary is on `$PATH`:
132135
133136
- uses: jakebailey/pyright-action@v1
134137
```
138+
139+
## Keeping Pyright and Pylance in sync
140+
141+
If you use Pylance as your language server, you'll likely want pyright-action to
142+
use the same version of `pyright` that Pylance does. The `pylance-version`
143+
option makes this easy.
144+
145+
If you allow VS Code to auto-update Pylance, then set `pylance-version` to
146+
`latest-release` if you use Pylance's Release builds, or `latest-prerelease` if
147+
you use Pylance's Pre-Release builds. Alternatively, you can set it to a
148+
particular Pylance version number (ex. `2023.11.11`).
149+
150+
Note that the `version` option takes precedence over `pylance-version`, so
151+
you'll want to set one or the other, not both.
152+
153+
```yml
154+
- uses: jakebailey/pyright-action@v1
155+
with:
156+
pylance-version: latest-release
157+
```

‎action.yml‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ branding:
88
inputs:
99
# Options for pyright-action
1010
version:
11-
description: 'Version of pyright to run. If not specified, the latest version will be used.'
11+
description: 'Version of pyright to run. If neither version nor pylance-version are specified, the latest version will be used.'
12+
required: false
13+
pylance-version:
14+
description: 'Version of pylance whose pyright version should be run. Can be latest-release, latest-prerelease, or a specific pylance version. Ignored if version option is specified.'
1215
required: false
1316
working-directory:
1417
description: 'Directory to run pyright in. If not specified, the repo root will be used.'

‎dist/index.js‎

Lines changed: 62 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,12 +1154,12 @@ var require_lib = __commonJS({
11541154
throw new Error("Client has already been disposed.");
11551155
}
11561156
const parsedUrl = new URL(requestUrl);
1157-
let info2 = this._prepareRequest(verb, parsedUrl, headers);
1157+
let info3 = this._prepareRequest(verb, parsedUrl, headers);
11581158
const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) ? this._maxRetries + 1 : 1;
11591159
let numTries = 0;
11601160
let response;
11611161
do {
1162-
response = yield this.requestRaw(info2, data);
1162+
response = yield this.requestRaw(info3, data);
11631163
if (response && response.message && response.message.statusCode === HttpCodes2.Unauthorized) {
11641164
let authenticationHandler;
11651165
for (const handler of this.handlers) {
@@ -1169,7 +1169,7 @@ var require_lib = __commonJS({
11691169
}
11701170
}
11711171
if (authenticationHandler) {
1172-
return authenticationHandler.handleAuthentication(this, info2, data);
1172+
return authenticationHandler.handleAuthentication(this, info3, data);
11731173
} else {
11741174
return response;
11751175
}
@@ -1192,8 +1192,8 @@ var require_lib = __commonJS({
11921192
}
11931193
}
11941194
}
1195-
info2 = this._prepareRequest(verb, parsedRedirectUrl, headers);
1196-
response = yield this.requestRaw(info2, data);
1195+
info3 = this._prepareRequest(verb, parsedRedirectUrl, headers);
1196+
response = yield this.requestRaw(info3, data);
11971197
redirectsRemaining--;
11981198
}
11991199
if (!response.message.statusCode || !HttpResponseRetryCodes.includes(response.message.statusCode)) {
@@ -1222,7 +1222,7 @@ var require_lib = __commonJS({
12221222
* @param info
12231223
* @param data
12241224
*/
1225-
requestRaw(info2, data) {
1225+
requestRaw(info3, data) {
12261226
return __awaiter(this, void 0, void 0, function* () {
12271227
return new Promise((resolve, reject) => {
12281228
function callbackForResult(err, res) {
@@ -1234,7 +1234,7 @@ var require_lib = __commonJS({
12341234
resolve(res);
12351235
}
12361236
}
1237-
this.requestRawWithCallback(info2, data, callbackForResult);
1237+
this.requestRawWithCallback(info3, data, callbackForResult);
12381238
});
12391239
});
12401240
}
@@ -1244,12 +1244,12 @@ var require_lib = __commonJS({
12441244
* @param data
12451245
* @param onResult
12461246
*/
1247-
requestRawWithCallback(info2, data, onResult) {
1247+
requestRawWithCallback(info3, data, onResult) {
12481248
if (typeof data === "string") {
1249-
if (!info2.options.headers) {
1250-
info2.options.headers = {};
1249+
if (!info3.options.headers) {
1250+
info3.options.headers = {};
12511251
}
1252-
info2.options.headers["Content-Length"] = Buffer.byteLength(data, "utf8");
1252+
info3.options.headers["Content-Length"] = Buffer.byteLength(data, "utf8");
12531253
}
12541254
let callbackCalled = false;
12551255
function handleResult(err, res) {
@@ -1258,7 +1258,7 @@ var require_lib = __commonJS({
12581258
onResult(err, res);
12591259
}
12601260
}
1261-
const req = info2.httpModule.request(info2.options, (msg) => {
1261+
const req = info3.httpModule.request(info3.options, (msg) => {
12621262
const res = new HttpClientResponse(msg);
12631263
handleResult(void 0, res);
12641264
});
@@ -1270,7 +1270,7 @@ var require_lib = __commonJS({
12701270
if (socket) {
12711271
socket.end();
12721272
}
1273-
handleResult(new Error(`Request timeout: ${info2.options.path}`));
1273+
handleResult(new Error(`Request timeout: ${info3.options.path}`));
12741274
});
12751275
req.on("error", function(err) {
12761276
handleResult(err);
@@ -1297,27 +1297,27 @@ var require_lib = __commonJS({
12971297
return this._getAgent(parsedUrl);
12981298
}
12991299
_prepareRequest(method, requestUrl, headers) {
1300-
const info2 = {};
1301-
info2.parsedUrl = requestUrl;
1302-
const usingSsl = info2.parsedUrl.protocol === "https:";
1303-
info2.httpModule = usingSsl ? https : http;
1300+
const info3 = {};
1301+
info3.parsedUrl = requestUrl;
1302+
const usingSsl = info3.parsedUrl.protocol === "https:";
1303+
info3.httpModule = usingSsl ? https : http;
13041304
const defaultPort = usingSsl ? 443 : 80;
1305-
info2.options = {};
1306-
info2.options.host = info2.parsedUrl.hostname;
1307-
info2.options.port = info2.parsedUrl.port ? parseInt(info2.parsedUrl.port) : defaultPort;
1308-
info2.options.path = (info2.parsedUrl.pathname || "") + (info2.parsedUrl.search || "");
1309-
info2.options.method = method;
1310-
info2.options.headers = this._mergeHeaders(headers);
1305+
info3.options = {};
1306+
info3.options.host = info3.parsedUrl.hostname;
1307+
info3.options.port = info3.parsedUrl.port ? parseInt(info3.parsedUrl.port) : defaultPort;
1308+
info3.options.path = (info3.parsedUrl.pathname || "") + (info3.parsedUrl.search || "");
1309+
info3.options.method = method;
1310+
info3.options.headers = this._mergeHeaders(headers);
13111311
if (this.userAgent != null) {
1312-
info2.options.headers["user-agent"] = this.userAgent;
1312+
info3.options.headers["user-agent"] = this.userAgent;
13131313
}
1314-
info2.options.agent = this._getAgent(info2.parsedUrl);
1314+
info3.options.agent = this._getAgent(info3.parsedUrl);
13151315
if (this.handlers) {
13161316
for (const handler of this.handlers) {
1317-
handler.prepareRequest(info2.options);
1317+
handler.prepareRequest(info3.options);
13181318
}
13191319
}
1320-
return info2;
1320+
return info3;
13211321
}
13221322
_mergeHeaders(headers) {
13231323
if (this.requestOptions && this.requestOptions.headers) {
@@ -2161,10 +2161,10 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``);
21612161
command_1.issueCommand("notice", utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message);
21622162
}
21632163
exports.notice = notice;
2164-
function info2(message) {
2164+
function info3(message) {
21652165
process.stdout.write(message + os.EOL);
21662166
}
2167-
exports.info = info2;
2167+
exports.info = info3;
21682168
function startGroup(name) {
21692169
command_1.issue("group", name);
21702170
}
@@ -6992,6 +6992,13 @@ var NpmRegistryResponse = object({
69926992
function parseNpmRegistryResponse(v) {
69936993
return NpmRegistryResponse.parse(v, { mode: "strip" });
69946994
}
6995+
var PylanceBuildMetadata = object({
6996+
pylanceVersion: string().assert(isSemVer, "must be a semver"),
6997+
pyrightVersion: string().assert(isSemVer, "must be a semver")
6998+
});
6999+
function parsePylanceBuildMetadata(v) {
7000+
return PylanceBuildMetadata.parse(v, { mode: "strip" });
7001+
}
69957002

69967003
// src/helpers.ts
69977004
function getActionVersion() {
@@ -7115,17 +7122,17 @@ function getBooleanInput(name, defaultValue) {
71157122
return input.toUpperCase() === "TRUE";
71167123
}
71177124
var pyrightToolName = "pyright";
7118-
async function downloadPyright(info2) {
7119-
const found = tc.find(pyrightToolName, info2.version);
7125+
async function downloadPyright(info3) {
7126+
const found = tc.find(pyrightToolName, info3.version);
71207127
if (found) {
71217128
return found;
71227129
}
7123-
const tarballPath = await tc.downloadTool(info2.dist.tarball);
7130+
const tarballPath = await tc.downloadTool(info3.dist.tarball);
71247131
const extractedPath = await tc.extractTar(tarballPath);
7125-
return await tc.cacheDir(extractedPath, pyrightToolName, info2.version);
7132+
return await tc.cacheDir(extractedPath, pyrightToolName, info3.version);
71267133
}
71277134
async function getPyrightInfo() {
7128-
const version3 = getPyrightVersion();
7135+
const version3 = await getPyrightVersion();
71297136
const client = new httpClient.HttpClient();
71307137
const resp = await client.get(`https://registry.npmjs.org/pyright/${version3}`);
71317138
const body = await resp.readBody();
@@ -7134,13 +7141,33 @@ async function getPyrightInfo() {
71347141
}
71357142
return parseNpmRegistryResponse(JSON.parse(body));
71367143
}
7137-
function getPyrightVersion() {
7144+
async function getPyrightVersion() {
71387145
const versionSpec = core.getInput("version");
71397146
if (versionSpec) {
71407147
return new import_semver2.default(versionSpec).format();
71417148
}
7149+
const pylanceVersion = core.getInput("pylance-version");
7150+
if (pylanceVersion) {
7151+
if (pylanceVersion !== "latest-release" && pylanceVersion !== "latest-prerelease") {
7152+
new import_semver2.default(pylanceVersion);
7153+
}
7154+
return await getPylancePyrightVersion(pylanceVersion);
7155+
}
71427156
return "latest";
71437157
}
7158+
async function getPylancePyrightVersion(pylanceVersion) {
7159+
const client = new httpClient.HttpClient();
7160+
const url = `https://raw.githubusercontent.com/microsoft/pylance-release/main/releases/${pylanceVersion}.json`;
7161+
const resp = await client.get(url);
7162+
const body = await resp.readBody();
7163+
if (resp.message.statusCode !== httpClient.HttpCodes.OK) {
7164+
throw new Error(`Failed to download release metadata for Pylance ${pylanceVersion} from ${url} -- ${body}`);
7165+
}
7166+
const buildMetadata = parsePylanceBuildMetadata(JSON.parse(body));
7167+
const pyrightVersion = buildMetadata.pyrightVersion;
7168+
core.info(`Pylance ${pylanceVersion} uses pyright ${pyrightVersion}`);
7169+
return pyrightVersion;
7170+
}
71447171

71457172
// src/main.ts
71467173
function printInfo(pyrightVersion, node, args) {

0 commit comments

Comments
 (0)