Skip to content

Commit 1b9ab1b

Browse files
Kevin/new plugin upgrade (node-pty + parallelization) (#13)
* feat: Updated to new pty plugin spawner and new testing library WIP (missing migrating some files) * feat: Fixed bugs and changed tests to new library that supports node-pty * feat: Added rollup configuration to package node-pty * feat: Added deploy system that deploys directly to cloudflare fix: Removed debug log statements * feat: Bumped library version * feat: Bumped library versions
1 parent becd180 commit 1b9ab1b

69 files changed

Lines changed: 427 additions & 437 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

esbuild.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { build } from 'esbuild';
2+
3+
const result = await build({
4+
entryPoints: ['src/index.ts'],
5+
bundle: true,
6+
minify: false,
7+
splitting: true,
8+
platform: 'node',
9+
outdir: 'dist',
10+
format: 'esm',
11+
loader: {
12+
'.node': 'file',
13+
'.cc': 'file',
14+
},
15+
// external: ['node-pty'],
16+
// packages: 'external',
17+
logLevel: 'debug',
18+
});
19+
20+
console.log(result);

package.json

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"name": "homebrew-plugin",
3-
"version": "1.0.0",
2+
"name": "default",
3+
"version": "0.11.0",
44
"description": "",
55
"main": "dist/index.js",
66
"scripts": {
@@ -12,7 +12,8 @@
1212
"test:integration": "vitest test/**/*.test.ts",
1313
"test": "vitest",
1414
"rollup": "rollup -c",
15-
"build": "tsx ./scripts/build.ts"
15+
"build": "tsx ./scripts/build.ts",
16+
"deploy": "tsx ./scripts/deploy.ts"
1617
},
1718
"keywords": [],
1819
"author": "",
@@ -22,20 +23,22 @@
2223
"ajv": "^8.12.0",
2324
"ajv-formats": "^2.1.1",
2425
"semver": "^7.6.0",
25-
"codify-plugin-lib": "1.0.107",
26-
"codify-schemas": "1.0.52",
26+
"codify-plugin-lib": "1.0.132",
27+
"codify-schemas": "1.0.63",
2728
"chalk": "^5.3.0",
2829
"debug": "^4.3.4",
2930
"plist": "^3.1.0",
3031
"lodash.isequal": "^4.5.0",
31-
"strip-ansi": "^7.1.0"
32+
"strip-ansi": "^7.1.0",
33+
"nanoid": "^5.0.9"
3234
},
3335
"devDependencies": {
3436
"rollup": "^4.12.0",
3537
"@rollup/plugin-json": "^6.1.0",
3638
"@rollup/plugin-typescript": "^11.1.6",
3739
"@rollup/plugin-commonjs": "^25.0.7",
3840
"@rollup/plugin-node-resolve": "^15.2.3",
41+
"@rollup/plugin-replace": "^6.0.2",
3942
"@rollup/plugin-terser": "^0.4.4",
4043
"@oclif/prettier-config": "^0.2.1",
4144
"@oclif/test": "^3",
@@ -47,7 +50,7 @@
4750
"@types/debug": "4.1.12",
4851
"@types/plist": "^3.0.5",
4952
"@types/lodash.isequal": "^4.5.8",
50-
"codify-plugin-test": "0.0.26",
53+
"codify-plugin-test": "0.0.47",
5154
"commander": "^12.1.0",
5255
"eslint": "^8.51.0",
5356
"eslint-config-oclif": "^5",

rollup.config.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
import typescript from '@rollup/plugin-typescript';
2-
import json from '@rollup/plugin-json';
31
import commonjs from '@rollup/plugin-commonjs';
2+
import json from '@rollup/plugin-json';
43
import nodeResolve from '@rollup/plugin-node-resolve';
54
import terser from '@rollup/plugin-terser';
5+
import typescript from '@rollup/plugin-typescript';
66

77
export default {
88
input: 'src/index.ts',
99
output: {
1010
dir:'dist',
1111
format: 'cjs'
1212
},
13+
external: ['@homebridge/node-pty-prebuilt-multiarch'],
1314
plugins: [
1415
json(),
15-
nodeResolve({ exportConditions: ['node']}),
16+
nodeResolve({ exportConditions: ['node'] }),
1617
typescript(),
1718
commonjs(),
1819
terser()

scripts/build.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import { Ajv } from 'ajv';
33
import { IpcMessage, IpcMessageSchema, MessageStatus, ResourceSchema } from 'codify-schemas';
44
import mergeJsonSchemas from 'merge-json-schemas';
55
import { ChildProcess, fork } from 'node:child_process';
6+
import fs from 'node:fs';
7+
import path from 'node:path';
8+
import * as url from 'node:url';
69

710
import { codifySpawn } from '../src/utils/codify-spawn.js';
811

@@ -88,8 +91,13 @@ const mergedSchemas = [...schemasMap.entries()].map(([type, schema]) => {
8891
await codifySpawn('rm -rf ./dist')
8992
await codifySpawn('npm run rollup'); // re-run rollup without building for es
9093

91-
console.log('JSON Schemas for all resources')
92-
console.log(JSON.stringify(mergedSchemas, null, 2));
94+
console.log('Generated JSON Schemas for all resources')
95+
96+
const distFolder = path.resolve(path.dirname(url.fileURLToPath(import.meta.url)), '..', 'dist');
97+
const schemaOutputPath = path.resolve(distFolder, 'schemas.json');
98+
fs.writeFileSync(schemaOutputPath, JSON.stringify(mergedSchemas, null, 2));
99+
100+
console.log('Successfully wrote schema to ./dist/schemas.json')
93101

94102
// eslint-disable-next-line n/no-process-exit,unicorn/no-process-exit
95103
process.exit(0)

scripts/deploy.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import * as cp from 'node:child_process';
2+
import path from 'node:path';
3+
import * as url from 'node:url';
4+
5+
// This should run the build
6+
cp.spawnSync('source ~/.zshrc; npm run build', { shell: 'zsh', stdio: 'inherit' });
7+
8+
const version = process.env.npm_package_version;
9+
if (!version) {
10+
throw new Error('Unable to find version');
11+
}
12+
13+
const name = process.env.npm_package_name;
14+
if (!name) {
15+
throw new Error('Unable to find package name');
16+
}
17+
18+
console.log(`Uploading plugin ${name}, version ${version} to cloudflare!`)
19+
20+
const outputFilePath = path.resolve(path.dirname(url.fileURLToPath(import.meta.url)), '..', 'dist', 'index.js')
21+
cp.spawnSync(`source ~/.zshrc; npx wrangler r2 object put plugins/${name}/${version}/index.js --file=${outputFilePath}`, { shell: 'zsh', stdio: 'inherit' });

scripts/run-tests.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,26 +67,30 @@ async function run(cmd: string, debug: boolean, simple = true) {
6767
const [_, ip] = data.toString().match(IP_REGEX);
6868

6969
console.log(`Copying ssh keys to ${ip}`)
70-
spawnSync(`source $HOME/.zshrc; sshpass -p admin ssh-copy-id -o "StrictHostKeyChecking=no" admin@${ip}`, { stdio: 'inherit', shell: 'zsh' });
70+
// spawnSync(`source $HOME/.zshrc; sshpass -p admin ssh-copy-id -o "StrictHostKeyChecking=no" admin@${ip}`, { stdio: 'inherit', shell: 'zsh' });
7171

7272
console.log('Enabling port forwarding')
73-
const portForward1 = spawn(`ssh -L 9229:localhost:9229 -Nf admin@${ip}`, { stdio: 'pipe', shell: 'zsh' });
73+
const sshStatement1 = `ssh${ Array.from({ length: 20 }, (i: number) => i + 9000).map((i) => ` -L ${i}:localhost:${i}`)} admin@${ip}`;
74+
const sshStatement2 = `source $HOME/.zshrc; sshpass -p admin ssh -L 9221:localhost:9221 -L 9229:localhost:9229 -N -o "StrictHostKeyChecking=no" admin@${ip}`
75+
76+
const portForward1 = spawn(sshStatement2, { stdio: 'pipe', shell: 'zsh' });
77+
portForward1.stderr.pipe(process.stdout)
7478
portForward1.stdout.on('data', data => {
7579
console.log(data.toString());
7680
if (data.toString().includes('Address already in use')) {
7781
throw new Error('Port 9229 already in use!')
7882
}
7983
})
80-
console.log('Enabled on port 9229')
81-
82-
const portForward2 = spawn(`ssh -L 9221:localhost:9221 -Nf admin@${ip}`, { stdio: 'pipe', shell: 'zsh' });
83-
portForward2.stdout.on('data', data => {
84-
console.log(data.toString());
85-
if (data.toString().includes('Address already in use')) {
86-
throw new Error('Port 9221 already in use!')
87-
}
88-
});
89-
console.log('Enabled on port 9221')
84+
// console.log('Enabled on port 9229')
85+
86+
// const portForward2 = spawn(`ssh -L 9221:localhost:9221 -Nf admin@${ip}`, { stdio: 'pipe', shell: 'zsh' });
87+
// portForward2.stdout.on('data', data => {
88+
// console.log(data.toString());
89+
// if (data.toString().includes('Address already in use')) {
90+
// throw new Error('Port 9221 already in use!')
91+
// }
92+
// });
93+
// console.log('Enabled on port 9221')
9094
}
9195
})
9296
}

src/resources/asdf/asdf-global.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { CreatePlan, DestroyPlan, Resource, ResourceSettings, } from 'codify-plugin-lib';
1+
import { CreatePlan, DestroyPlan, Resource, ResourceSettings, getPty, } from 'codify-plugin-lib';
22
import { ResourceConfig } from 'codify-schemas';
33
import os from 'node:os';
44
import path from 'node:path';
@@ -29,16 +29,15 @@ export class AsdfGlobalResource extends Resource<AsdfGlobalConfig> {
2929
}
3030

3131
async refresh(parameters: Partial<AsdfGlobalConfig>): Promise<Partial<AsdfGlobalConfig> | Partial<AsdfGlobalConfig>[] | null> {
32-
if ((await codifySpawn('which asdf', { throws: false })).status === SpawnStatus.ERROR) {
33-
return null;
34-
}
32+
const $ = getPty();
3533

36-
if ((await codifySpawn(`asdf list ${parameters.plugin}`, { throws: false })).status === SpawnStatus.ERROR) {
34+
const plugins = await $.spawnSafe(`asdf list ${parameters.plugin}`);
35+
if (plugins.status === SpawnStatus.ERROR) {
3736
return null;
3837
}
3938

4039
// Only check for the installed version matches if it's not latest. The latest version could be out of date.
41-
const installedVersions = new Set((await codifySpawn(`asdf list ${parameters.plugin}`))
40+
const installedVersions = new Set(plugins
4241
.data
4342
.split(/\n/)
4443
.filter(Boolean)
@@ -53,7 +52,7 @@ export class AsdfGlobalResource extends Resource<AsdfGlobalConfig> {
5352
return null;
5453
}
5554

56-
const { status } = await codifySpawn(`asdf current ${parameters.plugin}`, { throws: false, cwd: os.homedir() });
55+
const { status } = await $.spawnSafe(`asdf current ${parameters.plugin}`, { cwd: os.homedir() });
5756
return status === SpawnStatus.ERROR
5857
? null
5958
: parameters;

src/resources/asdf/asdf-install.ts

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { CreatePlan, DestroyPlan, Resource, ResourceSettings, untildify, } from 'codify-plugin-lib';
1+
import { CreatePlan, DestroyPlan, getPty, Resource, ResourceSettings, untildify, } from 'codify-plugin-lib';
22
import { ResourceConfig } from 'codify-schemas';
33
import * as fs from 'node:fs/promises';
44
import path from 'node:path';
@@ -26,12 +26,12 @@ export class AsdfInstallResource extends Resource<AsdfInstallConfig> {
2626
schema: AsdfInstallSchema,
2727
parameterSettings: {
2828
directory: { type: 'directory', inputTransformation: (input) => untildify(input) },
29-
versions: { type: 'stateful', definition: new AsdfPluginVersionsParameter() }
29+
versions: { type: 'array' }
3030
},
3131
import: {
3232
requiredParameters: ['directory'],
3333
refreshKeys: ['directory']
34-
}
34+
},
3535
}
3636
}
3737

@@ -50,15 +50,17 @@ export class AsdfInstallResource extends Resource<AsdfInstallConfig> {
5050
}
5151

5252
async refresh(parameters: Partial<AsdfInstallConfig>): Promise<Partial<AsdfInstallConfig> | Partial<AsdfInstallConfig>[] | null> {
53-
if ((await codifySpawn('which asdf', { throws: false })).status === SpawnStatus.ERROR) {
53+
const $ = getPty();
54+
55+
if ((await $.spawnSafe('which asdf')).status === SpawnStatus.ERROR) {
5456
return null;
5557
}
5658

5759
if (parameters.directory) {
5860
const desiredTools = await this.getToolVersions(parameters.directory);
5961

6062
for (const { plugin, version } of desiredTools) {
61-
const { status, data } = await codifySpawn(`asdf current ${plugin}`, { throws: false, cwd: parameters.directory });
63+
const { status, data } = await $.spawnSafe(`asdf current ${plugin}`, { cwd: parameters.directory });
6264
if (status === SpawnStatus.ERROR || data.trim() === '') {
6365
return null;
6466
}
@@ -74,12 +76,25 @@ export class AsdfInstallResource extends Resource<AsdfInstallConfig> {
7476
};
7577
}
7678

77-
if ((await codifySpawn('which asdf', { throws: false })).status === SpawnStatus.ERROR) {
79+
// Directly check plugin version
80+
const versionsQuery = await $.spawnSafe(`asdf list ${parameters.plugin}`);
81+
if (versionsQuery.status === SpawnStatus.ERROR || versionsQuery.data.trim() === 'No versions installed') {
7882
return null;
7983
}
8084

85+
const latest = parameters.versions?.includes('latest')
86+
? (await codifySpawn(`asdf latest ${parameters.plugin}`)).data.trim()
87+
: null;
88+
89+
const versions = versionsQuery.data.split(/\n/)
90+
.map((l) => l.trim())
91+
.map((l) => l.replaceAll('*', ''))
92+
.map((l) => l.trim() === latest ? 'latest' : l)
93+
.filter(Boolean);
94+
8195
return {
8296
plugin: parameters.plugin,
97+
versions,
8398
}
8499
}
85100

@@ -95,7 +110,10 @@ export class AsdfInstallResource extends Resource<AsdfInstallConfig> {
95110
}
96111

97112
await codifySpawn('asdf install', { cwd: plan.desiredConfig.directory });
113+
return;
98114
}
115+
116+
await codifySpawn(`asdf install ${plan.desiredConfig?.plugin} ${plan.desiredConfig.versions?.join(' ')}`);
99117
}
100118

101119
async destroy(plan: DestroyPlan<AsdfInstallConfig>): Promise<void> {
@@ -106,7 +124,12 @@ export class AsdfInstallResource extends Resource<AsdfInstallConfig> {
106124
for (const { plugin, version } of desiredTools) {
107125
await codifySpawn(`asdf uninstall ${plugin} ${version}`);
108126
}
127+
128+
return;
109129
}
130+
131+
// Other path is uninstalled through the stateful parameter
132+
await codifySpawn(`asdf uninstall ${plan.currentConfig?.plugin} ${plan.currentConfig.versions?.join(' ')}`);
110133
}
111134

112135
private async getToolVersions(directory: string): Promise<Array<{ plugin: string; version: string }>> {

src/resources/asdf/asdf-local.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
import { CreatePlan, DestroyPlan, ModifyPlan, ParameterChange, Resource, ResourceSettings, } from 'codify-plugin-lib';
1+
import {
2+
CreatePlan,
3+
DestroyPlan,
4+
getPty,
5+
ModifyPlan,
6+
ParameterChange,
7+
Resource,
8+
ResourceSettings,
9+
} from 'codify-plugin-lib';
210
import { ResourceConfig } from 'codify-schemas';
311
import * as fs from 'node:fs';
412
import path from 'node:path';
@@ -66,16 +74,15 @@ export class AsdfLocalResource extends Resource<AsdfLocalConfig> {
6674
}
6775

6876
async refresh(parameters: Partial<AsdfLocalConfig>): Promise<Partial<AsdfLocalConfig> | Partial<AsdfLocalConfig>[] | null> {
69-
if ((await codifySpawn('which asdf', { throws: false })).status === SpawnStatus.ERROR) {
70-
return null;
71-
}
77+
const $ = getPty();
7278

73-
if ((await codifySpawn(`asdf list ${parameters.plugin}`, { throws: false })).status === SpawnStatus.ERROR) {
79+
const plugins = await $.spawnSafe(`asdf list ${parameters.plugin}`);
80+
if (plugins.status === SpawnStatus.ERROR) {
7481
return null;
7582
}
7683

7784
// Only check for the installed version matches if it's not latest. The latest version could be out of date.
78-
const installedVersions = new Set((await codifySpawn(`asdf list ${parameters.plugin}`))
85+
const installedVersions = new Set(plugins
7986
.data
8087
.split(/\n/)
8188
.filter(Boolean)
@@ -91,7 +98,7 @@ export class AsdfLocalResource extends Resource<AsdfLocalConfig> {
9198
}
9299

93100
if (parameters.directory) {
94-
const { status, data } = await codifySpawn(`asdf current ${parameters.plugin}`, { throws: false, cwd: parameters.directory });
101+
const { status, data } = await $.spawnSafe(`asdf current ${parameters.plugin}`, { cwd: parameters.directory });
95102

96103
if (status === SpawnStatus.ERROR || data.trim() === '') {
97104
return null;
@@ -109,7 +116,7 @@ export class AsdfLocalResource extends Resource<AsdfLocalConfig> {
109116
let versionUpToDate = true;
110117
let latestVersion = null;
111118
for (const dir of parameters.directories!) {
112-
const { status, data } = await codifySpawn(`asdf current ${parameters.plugin}`, { throws: false, cwd: dir });
119+
const { status, data } = await $.spawnSafe(`asdf current ${parameters.plugin}`, { cwd: dir });
113120
if (status === SpawnStatus.ERROR || data.trim() === '') {
114121
continue;
115122
}
@@ -173,9 +180,7 @@ export class AsdfLocalResource extends Resource<AsdfLocalConfig> {
173180
}
174181

175182
for (const dir of plan.currentConfig.directories!) {
176-
console.log(path.join(dir, '.tool-versions'))
177183
await FileUtils.removeLineFromFile(path.join(dir, '.tool-versions'), plan.currentConfig.plugin);
178-
console.log(fs.readFileSync(path.join(dir, '.tool-versions')).toString());
179184
}
180185
}
181186
}

src/resources/asdf/asdf-plugin.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { CreatePlan, DestroyPlan, Resource, ResourceSettings, SpawnStatus, } from 'codify-plugin-lib';
1+
import { CreatePlan, DestroyPlan, Resource, ResourceSettings, SpawnStatus, untildify } from 'codify-plugin-lib';
22
import { ResourceConfig } from 'codify-schemas';
33

44
import { codifySpawn } from '../../utils/codify-spawn.js';
@@ -37,7 +37,6 @@ export class AsdfPluginResource extends Resource<AsdfPluginConfig> {
3737
.map((l) => l.trim())
3838
.map((l) => l.replaceAll('*', ''))
3939
.map((l) => {
40-
console.log(l);
4140
const matches = l.match(PLUGIN_LIST_REGEX)
4241
if (!matches) {
4342
return null;

0 commit comments

Comments
 (0)