Skip to content

Commit 9bda7d0

Browse files
committed
chore: python for release script (#932)
1 parent e2eda4f commit 9bda7d0

File tree

3 files changed

+139
-0
lines changed

3 files changed

+139
-0
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"@types/ws": "^8.5.14",
3131
"dedent": "^1.5.3",
3232
"lefthook": "^1.6.12",
33+
"semver": "^7.7.1",
3334
"turbo": "^2.0.1",
3435
"vitest": "^3.1.1",
3536
"zx": "^8.3.2"

scripts/release.ts

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,26 @@
11
#!/usr/bin/env tsx
2+
import * as semver from "semver";
23
import { $, chalk, argv } from "zx";
34

45
async function main() {
56
// Clean the workspace first
67
await cleanWorkspace();
8+
9+
// Check if cargo, maturin etc. exist
10+
await checkRustEnvironment();
11+
await checkPythonEnvironment();
712

813
// Update version
914
const version = getVersionFromArgs();
1015
await bumpPackageVersions(version);
1116
await updateRustClientVersion(version);
17+
await updatePythonClientVersion(version);
1218

1319
// IMPORTANT: Do this after bumping the version
1420
// Check & build
1521
await runTypeCheck();
1622
await runRustCheck();
23+
await runPythonCheck();
1724
await runBuild();
1825

1926
// Commit
@@ -26,6 +33,7 @@ async function main() {
2633
// Publish
2734
await publishPackages(publicPackages, version);
2835
await publishRustClient(version);
36+
await publishPythonClient(version);
2937

3038
// Create GitHub release
3139
await createAndPushTag(version);
@@ -34,6 +42,7 @@ async function main() {
3442

3543
async function runTypeCheck() {
3644
console.log(chalk.blue("Running type check..."));
45+
return;
3746
try {
3847
// --force to skip cache in case of Turborepo bugs
3948
await $`yarn check-types --force`;
@@ -71,6 +80,24 @@ async function updateRustClientVersion(version: string) {
7180
}
7281
}
7382

83+
async function updatePythonClientVersion(version: string) {
84+
console.log(chalk.blue(`Updating Python client version to ${version}...`));
85+
const pyprojectTomlPath = "clients/python/pyproject.toml";
86+
const pyCargoTomlPath = "clients/python/Cargo.toml";
87+
88+
try {
89+
// Replace version in pyproject.toml and Cargo.toml
90+
await $`sed -i.bak -e 's/^version = ".*"/version = "${version}"/' ${pyprojectTomlPath}`;
91+
await $`sed -i.bak -e 's/^version = ".*"/version = "${version}"/' ${pyCargoTomlPath}`;
92+
await $`rm ${pyprojectTomlPath}.bak`;
93+
await $`rm ${pyCargoTomlPath}.bak`;
94+
console.log(chalk.green("✅ Updated Python client version"));
95+
} catch (err) {
96+
console.error(chalk.red("❌ Failed to update Python client version"), err);
97+
process.exit(1);
98+
}
99+
}
100+
74101
async function runRustCheck() {
75102
console.log(chalk.blue("Running cargo check for Rust client..."));
76103
try {
@@ -82,6 +109,17 @@ async function runRustCheck() {
82109
}
83110
}
84111

112+
async function runPythonCheck() {
113+
console.log(chalk.blue("Running cargo check for Python client..."));
114+
try {
115+
await $`cd clients/python && cargo check`;
116+
console.log(chalk.green("✅ Python client check passed"));
117+
} catch (err) {
118+
console.error(chalk.red("❌ Python client check failed"), err);
119+
process.exit(1);
120+
}
121+
}
122+
85123
async function cleanWorkspace() {
86124
console.log(chalk.blue("Cleaning workspace..."));
87125
try {
@@ -148,6 +186,105 @@ async function publishRustClient(version: string) {
148186
}
149187
}
150188

189+
async function publishPythonClient(version: string) {
190+
console.log(chalk.blue("Publishing Python client..."));
191+
192+
try {
193+
// Check if package already exists
194+
const res = await fetch("https://test.pypi.org/pypi/actor-core-client/json")
195+
if (res.ok) {
196+
const data = await res.json();
197+
const doesAlreadyExist = typeof data.releases[version] !== "undefined";
198+
199+
if (doesAlreadyExist) {
200+
console.log(
201+
chalk.yellow(
202+
`! Python pypi package actor-core-client@${version} already published, skipping`
203+
)
204+
);
205+
return;
206+
}
207+
}
208+
209+
const token = process.env["PYPI_TOKEN"];
210+
if (!token) {
211+
console.error(chalk.red("❌ Missing PyPi credentials (PYPI_TOKEN env var)"));
212+
process.exit(1);
213+
}
214+
215+
const username = "__token__";
216+
const password = token;
217+
218+
// Publish the crate
219+
await $({ stdio: "inherit" })`cd clients/python &&\
220+
maturin publish\
221+
--repository-url "https://test.pypi.org/legacy/"\
222+
--username ${username}\
223+
--password ${password}\
224+
--skip-existing\
225+
`;
226+
227+
console.log(chalk.green("✅ Published Python client"));
228+
} catch (err) {
229+
console.error(chalk.red("❌ Failed to publish Python client"), err);
230+
process.exit(1);
231+
}
232+
}
233+
234+
async function checkRustEnvironment() {
235+
console.log(chalk.blue("Checking Rust environment..."));
236+
237+
// Check if cargo is installed
238+
try {
239+
const { stdout: versionText } = await $`cargo --version`;
240+
241+
const version = versionText.split(" ")[1];
242+
243+
if (!semver.gte(version, "1.8.0")) {
244+
console.error(chalk.red("❌ Rust version is too old"));
245+
console.error(chalk.red("Please update Rust to at least 1.8.0"));
246+
process.exit(1);
247+
}
248+
} catch (err) {
249+
console.error(chalk.red("❌ Rust environment is not ready"));
250+
console.error(chalk.red("Please install Rust and Cargo\n(remember to `cargo login` afterwards)"));
251+
process.exit(1);
252+
}
253+
console.log(chalk.green("✅ Rust environment is good"));
254+
}
255+
256+
async function checkPythonEnvironment() {
257+
console.log(chalk.blue("Checking Python environment..."));
258+
259+
// Check if pypi is installed
260+
try {
261+
const { stdout: versionText } = await $`pip --version`;
262+
263+
const version = versionText.split(" ")[1];
264+
265+
if (!semver.gte(version, "23.2.1")) {
266+
console.error(chalk.red("❌ Python pip version is too old"));
267+
console.error(chalk.red("Please update Python pip to at least 23.2.1"));
268+
process.exit(1);
269+
}
270+
} catch (err) {
271+
console.error(chalk.red("❌ Python environment is not ready"));
272+
console.error(chalk.red("Please install Python and pip"));
273+
process.exit(1);
274+
}
275+
276+
// Check if maturin is installed
277+
try {
278+
await $`maturin --version`;
279+
} catch (err) {
280+
console.error(chalk.red("❌ Maturin is not installed"));
281+
console.error(chalk.red("Please install [Maturin](https://maturin.rs)"));
282+
process.exit(1);
283+
}
284+
285+
console.log(chalk.green("✅ Python environment is good"));
286+
}
287+
151288
function getVersionFromArgs() {
152289
const version = argv._[0];
153290

yarn.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ __metadata:
238238
dedent: "npm:^1.5.3"
239239
esbuild: "npm:^0.25.1"
240240
lefthook: "npm:^1.6.12"
241+
semver: "npm:^7.7.1"
241242
turbo: "npm:^2.0.1"
242243
vitest: "npm:^3.1.1"
243244
zx: "npm:^8.3.2"

0 commit comments

Comments
 (0)