Skip to content

Commit 99f9924

Browse files
Merge pull request #12 from stackql/dev/upgrade
Dev/upgrade
2 parents eaf637a + 1e778ca commit 99f9924

4 files changed

Lines changed: 269 additions & 40 deletions

File tree

src/services/downloader.test.ts

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,49 @@
11
import { assertExists } from "https://deno.land/std@0.206.0/assert/assert_exists.ts";
22
import { Downloader } from "./downloader.ts";
33
import { removeStackQLDownload } from "../../testing/utils.ts";
4+
import {
5+
assertSpyCalls,
6+
spy,
7+
} from "https://deno.land/std@0.207.0/testing/mock.ts";
48

5-
Deno.test("Downloader setupStackQL Integration Test", async () => {
9+
Deno.test("Downloader setupStackQL and upgrade Test", async () => {
610
// Arrange
711
await removeStackQLDownload();
812
const downloader = new Downloader();
913
let binaryPath: string;
14+
const denoOpenSpy = spy(Deno, "open");
1015

1116
// Act
12-
try {
13-
binaryPath = await downloader.setupStackQL();
17+
const setupTest = async () => {
18+
try {
19+
binaryPath = await downloader.setupStackQL();
1420

15-
// Assert
16-
assertExists(binaryPath);
17-
// Check if the binary exists after setupStackQL is called
21+
// Assert
22+
assertExists(binaryPath);
23+
assertSpyCalls(denoOpenSpy, 1);
24+
// Check if the binary exists after setupStackQL is called
1825

19-
console.log(
20-
"Test passed: setupStackQL completed without errors and binary exists.",
21-
);
22-
} catch (error) {
23-
console.error("Test failed:", error);
24-
throw error; // This will cause the test to fail
25-
}
26+
console.log(
27+
"Test passed: setupStackQL completed without errors and binary exists."
28+
);
29+
} catch (error) {
30+
console.error("Test failed:", error);
31+
throw error; // This will cause the test to fail
32+
}
33+
};
34+
35+
const upgradeTest = async () => {
36+
try {
37+
binaryPath = await downloader.upgradeStackQL();
38+
39+
assertExists(binaryPath);
40+
assertSpyCalls(denoOpenSpy, 2);
41+
} catch (error) {
42+
console.error("Test failed:", error);
43+
throw error; // This will cause the test to fail
44+
}
45+
};
46+
47+
await setupTest();
48+
await upgradeTest();
2649
});

src/services/downloader.ts

Lines changed: 60 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ export class Downloader {
77
private os: string;
88
private arch: string;
99
private urlMap: Record<string, string>;
10-
1110
constructor() {
1211
this.os = Deno.build.os; // 'linux', 'darwin', or 'windows'
1312
this.arch = Deno.build.arch; // 'x86_64', 'arm64', etc.
@@ -25,11 +24,13 @@ export class Downloader {
2524

2625
private async downloadFile(url: string, downloadDir: string) {
2726
const res = await fetch(url);
27+
// create dir if not exists
28+
2829
const file = await Deno.open(downloadDir, { create: true, write: true });
2930

3031
try {
3132
await res.body?.pipeTo(file.writable).finally(
32-
() => file.close(), //TODO: fix bad resource id when closing file
33+
() => file.close() //TODO: fix bad resource id when closing file
3334
);
3435
} catch (error) {
3536
console.error(`ERROR: [downloadFile] ${error.message}`);
@@ -69,20 +70,7 @@ export class Downloader {
6970
return binaryMap[binaryOs];
7071
}
7172

72-
/**
73-
* Gets download dir
74-
* @returns download dir
75-
*/
76-
private async getDownloadDir(): Promise<string> {
77-
const projectDir = Deno.cwd();
78-
console.log("Project dir:", projectDir);
79-
80-
if (!projectDir) {
81-
throw new Error("Unable to determine the project directory.");
82-
}
83-
84-
const downloadDir = join(projectDir, ".stackql");
85-
73+
private async createDownloadDir(downloadDir: string) {
8674
try {
8775
const stat = await Deno.stat(downloadDir);
8876
if (!stat.isDirectory) {
@@ -95,6 +83,19 @@ export class Downloader {
9583
throw error;
9684
}
9785
}
86+
}
87+
/**
88+
* Gets download dir
89+
* @returns download dir
90+
*/
91+
private getDownloadDir(): string {
92+
const projectDir = Deno.cwd();
93+
94+
if (!projectDir) {
95+
throw new Error("Unable to determine the project directory.");
96+
}
97+
98+
const downloadDir = join(projectDir, ".stackql");
9899

99100
return downloadDir;
100101
}
@@ -121,33 +122,68 @@ export class Downloader {
121122
const unpacker = Deno.build.os === "darwin" ? darwinUnpack : unzip;
122123
await unpacker({ downloadDir, archiveFileName });
123124
}
125+
124126
private async setExecutable(binaryPath: string) {
125127
const allowExecOctal = 0o755;
126128
await osUtils.chomod(binaryPath, allowExecOctal);
127129
}
130+
131+
private async downloadAndInstallStackQL({
132+
downloadDir,
133+
binaryName,
134+
}: {
135+
downloadDir: string;
136+
binaryName: string;
137+
}) {
138+
const binaryPath = join(downloadDir, binaryName);
139+
await this.installStackQL(downloadDir);
140+
await this.setExecutable(binaryPath);
141+
return binaryPath;
142+
}
128143
/**
129144
* Setup stackql binary, check if binary exists, if not download it
130145
*/
131146
public async setupStackQL() {
132-
console.log("Installing stackql...");
133-
134147
try {
135148
const binaryName = this.getBinaryName();
136-
const downloadDir = await this.getDownloadDir();
137-
const binaryPath = join(downloadDir, binaryName);
149+
const downloadDir = this.getDownloadDir();
150+
await this.createDownloadDir(downloadDir);
151+
152+
let binaryPath = join(downloadDir, binaryName);
153+
138154
if (this.binaryExists(binaryName, downloadDir)) {
139-
console.log("stackql is already installed");
140155
await this.setExecutable(binaryPath);
141156
return binaryPath;
142157
}
143158

144-
console.log("Downloading stackql binary");
145-
await this.installStackQL(downloadDir);
146-
await this.setExecutable(binaryPath);
159+
binaryPath = await this.downloadAndInstallStackQL({
160+
downloadDir,
161+
binaryName,
162+
});
147163
return binaryPath;
148164
} catch (error) {
149165
console.error(`ERROR: [setup] ${error.message}`);
150166
Deno.exit(1);
151167
}
152168
}
169+
170+
private async removeStackQL() {
171+
const downloadDir = this.getDownloadDir();
172+
await Deno.remove(join(downloadDir, "/"), { recursive: true });
173+
console.log("stackql download dir removed");
174+
}
175+
176+
public async upgradeStackQL() {
177+
if (Deno.build.os === "darwin") {
178+
await this.removeStackQL();
179+
}
180+
const binaryName = this.getBinaryName();
181+
const downloadDir = this.getDownloadDir();
182+
await this.createDownloadDir(downloadDir);
183+
const binaryPath = await this.downloadAndInstallStackQL({
184+
downloadDir,
185+
binaryName,
186+
});
187+
return binaryPath;
188+
}
153189
}

src/stackql.test.ts

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,45 @@ Deno.test("Set properties from configs", async () => {
7676
assertSpyCall(runCliSpy, 0, {
7777
args: [binaryPath, ["exec", githubTestQuery, ...params]],
7878
});
79+
runCliSpy.restore();
80+
});
81+
82+
Deno.test("Set proxy properties from configs", async () => {
83+
await setupStackQL();
84+
const runCommandSpy = spy(osUtils, "runCommand");
85+
const stackQL = new StackQL();
86+
await stackQL.initialize({
87+
serverMode: false,
88+
proxyHost: "localhost",
89+
proxyPort: 8080,
90+
proxyUser: "user",
91+
proxyPassword: "password",
92+
proxyScheme: "https",
93+
});
94+
const githubTestQuery =
95+
`SELECT id, name from github.repos.repos where org='stackql'`;
96+
97+
await stackQL.runQuery(githubTestQuery);
98+
99+
const params = stackQL.getParams();
100+
assertEquals(params, [
101+
"--http.proxy.host",
102+
"localhost",
103+
"--http.proxy.port",
104+
"8080",
105+
"--http.proxy.user",
106+
"user",
107+
"--http.proxy.password",
108+
"password",
109+
"--http.proxy.scheme",
110+
"https",
111+
]);
112+
const binaryPath = stackQL.getBinaryPath();
113+
assert(binaryPath);
114+
assertSpyCall(runCommandSpy, 0, {
115+
args: [binaryPath, ["exec", githubTestQuery, ...params]],
116+
});
117+
runCommandSpy.restore();
79118
});
80119

81120
Deno.test("StackQL runServerQuery", async () => {
@@ -108,3 +147,64 @@ Deno.test("StackQL runServerQuery", async () => {
108147
await stackQL.closeConnection();
109148
}
110149
});
150+
151+
Deno.test("getVersion", async () => {
152+
await setupStackQL();
153+
const stackQL = new StackQL();
154+
await stackQL.initialize({ serverMode: false });
155+
const versionRegex = /^v?(\d+(?:\.\d+)*)$/;
156+
const shaRegex = /^[a-f0-9]{7}$/;
157+
158+
const { version, sha } = await stackQL.getVersion();
159+
160+
assert(version);
161+
assert(sha);
162+
assert(versionRegex.test(version));
163+
assert(shaRegex.test(sha));
164+
});
165+
166+
Deno.test("getVersion when version and sha are undefined", async () => {
167+
await setupStackQL();
168+
const stackQL = new StackQL();
169+
await stackQL.initialize({ serverMode: false });
170+
const versionRegex = /^v?(\d+(?:\.\d+)*)$/;
171+
const shaRegex = /^[a-f0-9]{7}$/;
172+
// deno-lint-ignore no-explicit-any
173+
(stackQL as any).version = undefined;
174+
// deno-lint-ignore no-explicit-any
175+
(stackQL as any).sha = undefined;
176+
// deno-lint-ignore no-explicit-any
177+
assert((stackQL as any).version === undefined);
178+
// deno-lint-ignore no-explicit-any
179+
assert((stackQL as any).sha === undefined);
180+
181+
const { version, sha } = await stackQL.getVersion();
182+
183+
assert(version);
184+
assert(sha);
185+
assert(versionRegex.test(version));
186+
assert(shaRegex.test(sha));
187+
});
188+
189+
Deno.test("upgrade stackql", async () => {
190+
await setupStackQL();
191+
const stackQL = new StackQL();
192+
await stackQL.initialize({ serverMode: false });
193+
// deno-lint-ignore no-explicit-any
194+
(stackQL as any).version = undefined;
195+
// deno-lint-ignore no-explicit-any
196+
(stackQL as any).sha = undefined;
197+
const versionRegex = /^v?(\d+(?:\.\d+)*)$/;
198+
const shaRegex = /^[a-f0-9]{7}$/;
199+
// deno-lint-ignore no-explicit-any
200+
assert((stackQL as any).version === undefined);
201+
// deno-lint-ignore no-explicit-any
202+
assert((stackQL as any).sha === undefined);
203+
204+
const { version, sha } = await stackQL.upgrade();
205+
206+
assert(version);
207+
assert(sha);
208+
assert(versionRegex.test(version));
209+
assert(shaRegex.test(sha));
210+
});

0 commit comments

Comments
 (0)