Skip to content

Commit 8c5d5bd

Browse files
authored
feat(testing): Use temporal.download for downloading test server (#864)
1 parent 294705f commit 8c5d5bd

File tree

11 files changed

+71
-99
lines changed

11 files changed

+71
-99
lines changed

.github/workflows/ci.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ jobs:
3030
- uses: actions/setup-node@v1
3131
with:
3232
node-version: ${{ matrix.node }}
33+
- uses: Swatinem/rust-cache@v1
34+
with:
35+
working-directory: packages/core-bridge
3336
# Don't build during install phase since we're going to explicitly build
3437
- run: npm ci --ignore-scripts
3538
- run: npm run build
@@ -162,6 +165,9 @@ jobs:
162165
- name: Install gcc-aarch64-linux-gnu
163166
run: sudo apt update && sudo apt install -y gcc-aarch64-linux-gnu
164167
if: ${{ matrix.target == 'aarch64-unknown-linux-gnu' }}
168+
- uses: Swatinem/rust-cache@v1
169+
with:
170+
working-directory: packages/core-bridge
165171
# Don't build during install phase since we're going to explicitly build
166172
- run: npm ci --ignore-scripts
167173
- name: Compile all non-rust code

.github/workflows/stress.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ jobs:
3030
- uses: actions/setup-node@v1
3131
with:
3232
node-version: ${{ matrix.node }}
33+
- uses: Swatinem/rust-cache@v1
34+
with:
35+
working-directory: packages/core-bridge
3336
# Don't build during install phase since we're going to explicitly build
3437
- run: npm ci --ignore-scripts
3538
- run: npm run build

packages/client/src/workflow-options.ts

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -64,30 +64,3 @@ export interface WorkflowSignalWithStartOptionsWithArgs<SignalArgs extends any[]
6464
*/
6565
signalArgs: SignalArgs;
6666
}
67-
68-
// export interface WorkflowOptionsWithDefaults<T extends Workflow> extends CommonWorkflowOptionsWithDefaults<T> {
69-
// /**
70-
// * If set to true, instructs the client to follow the chain of execution before returning a Workflow's result.
71-
// *
72-
// * Workflow execution is chained if the Workflow has a cron schedule or continues-as-new or configured to retry
73-
// * after failure or timeout.
74-
// *
75-
// * @default true
76-
// */
77-
// followRuns: boolean;
78-
// }
79-
//
80-
// /**
81-
// * Adds default values to `workflowId` and `workflowIdReusePolicy` to given workflow options.
82-
// */
83-
// export function addDefaults<T extends Workflow>(
84-
// opts: WithWorkflowArgs<T, WorkflowOptions>
85-
// ): WorkflowOptionsWithDefaults<T> {
86-
// const { workflowId, args, ...rest } = opts;
87-
// return {
88-
// followRuns: true,
89-
// args: args ?? [],
90-
// workflowId: workflowId ?? uuid4(),
91-
// ...rest,
92-
// };
93-
// }

packages/common/src/failure.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export enum TimeoutType {
1616
}
1717

1818
checkExtends<temporal.api.enums.v1.TimeoutType, TimeoutType>();
19+
checkExtends<TimeoutType, temporal.api.enums.v1.TimeoutType>();
1920

2021
// Avoid importing the proto implementation to reduce workflow bundle size
2122
// Copied from temporal.api.enums.v1.RetryState
@@ -31,6 +32,7 @@ export enum RetryState {
3132
}
3233

3334
checkExtends<temporal.api.enums.v1.RetryState, RetryState>();
35+
checkExtends<RetryState, temporal.api.enums.v1.RetryState>();
3436

3537
export type WorkflowExecution = temporal.api.common.v1.IWorkflowExecution;
3638

packages/internal-workflow-common/src/activity-options.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export enum ActivityCancellationType {
1111
}
1212

1313
checkExtends<coresdk.workflow_commands.ActivityCancellationType, ActivityCancellationType>();
14+
checkExtends<ActivityCancellationType, coresdk.workflow_commands.ActivityCancellationType>();
1415

1516
/**
1617
* Options for remote activity invocation

packages/internal-workflow-common/src/workflow-options.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,15 @@ export enum WorkflowIdReusePolicy {
3636
* The Workflow cannot be started.
3737
*/
3838
WORKFLOW_ID_REUSE_POLICY_REJECT_DUPLICATE = 3,
39+
40+
/**
41+
* Terminate the current workflow if one is already running.
42+
*/
43+
WORKFLOW_ID_REUSE_POLICY_TERMINATE_IF_RUNNING = 4,
3944
}
4045

4146
checkExtends<temporal.api.enums.v1.WorkflowIdReusePolicy, WorkflowIdReusePolicy>();
47+
checkExtends<WorkflowIdReusePolicy, temporal.api.enums.v1.WorkflowIdReusePolicy>();
4248

4349
export interface BaseWorkflowOptions {
4450
/**

packages/test/src/load/worker.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,13 @@ async function main() {
157157
});
158158

159159
await withOptionalStatusServer(worker, statusPort, async () => {
160-
await worker.run();
161-
await connection.close();
160+
const interval = setInterval(() => logger.info('worker status', worker.getStatus()), 5000);
161+
try {
162+
await worker.run();
163+
} finally {
164+
clearInterval(interval);
165+
await connection.close();
166+
}
162167
});
163168
});
164169
}

packages/testing/scripts/common.mjs

Lines changed: 0 additions & 18 deletions
This file was deleted.

packages/testing/scripts/download-test-server.mjs

Lines changed: 43 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,29 @@ import stream from 'node:stream';
22
import util from 'node:util';
33
import zlib from 'node:zlib';
44
import fs from 'node:fs';
5+
import os from 'node:os';
56
import got from 'got';
67
import tar from 'tar-stream';
78
import unzipper from 'unzipper';
8-
import { outputPath, systemArch, systemPlatform } from './common.mjs';
9+
import { URL, fileURLToPath } from 'node:url';
10+
11+
const platformMapping = { darwin: 'darwin', linux: 'linux', win32: 'windows' };
12+
const archAlias = { x64: 'amd64', arm64: 'arm64' };
13+
14+
const platform = platformMapping[os.platform()];
15+
if (!platform) {
16+
throw new Error(`Unsupported platform ${os.platform()}`);
17+
}
18+
19+
const arch = archAlias[os.arch()];
20+
if (!arch) {
21+
throw new Error(`Unsupported architecture ${os.arch()}`);
22+
}
23+
24+
const ext = platform === 'windows' ? '.exe' : '';
25+
const outputPath = fileURLToPath(new URL(`../test-server${ext}`, import.meta.url));
26+
const pkgPath = fileURLToPath(new URL(`../package.json`, import.meta.url));
27+
const pkg = JSON.parse(fs.readFileSync(pkgPath));
928

1029
try {
1130
if (fs.statSync(outputPath).isFile) {
@@ -20,72 +39,44 @@ try {
2039

2140
const pipeline = util.promisify(stream.pipeline);
2241

23-
const defaultHeaders = {
24-
'User-Agent': '@temporalio/testing installer',
25-
};
26-
27-
const { GITHUB_TOKEN } = process.env;
28-
29-
if (GITHUB_TOKEN) {
30-
console.log(`Using GITHUB_TOKEN`);
31-
defaultHeaders['Authorization'] = `Bearer ${GITHUB_TOKEN}`;
32-
}
33-
34-
const latestReleaseRes = await got('https://api.github.com/repos/temporalio/sdk-java/releases/latest', {
42+
const defaultOptions = {
3543
headers: {
36-
...defaultHeaders,
37-
Accept: 'application/vnd.github.v3+json',
44+
'User-Agent': '@temporalio/testing installer',
3845
},
39-
}).json();
46+
};
4047

41-
function findTestServerAsset(assets) {
42-
for (const asset of assets) {
43-
const m = asset.name.match(/^temporal-test-server_[^_]+_([^_]+)_([^.]+)\.(?:zip|tar.gz)$/);
44-
if (m) {
45-
const [_, assetPlatform, _assetArch] = m;
46-
if (assetPlatform === systemPlatform) {
47-
// TODO: assetArch === systemArch (no arm builds for test server yet)
48-
return asset;
49-
}
50-
}
51-
}
52-
throw new Error(`No prebuilt test server for ${systemPlatform}-${systemArch}`);
53-
}
48+
const lookupOptions = {
49+
...defaultOptions,
50+
searchParams: { 'sdk-name': 'typescript', 'sdk-version': pkg.version, platform, arch },
51+
};
5452

55-
const asset = findTestServerAsset(latestReleaseRes.assets);
56-
console.log('Downloading test server', { asset: asset.name, outputPath });
53+
const lookupUrl = 'https://temporal.download/temporal-test-server/default';
54+
console.log('Looking up default test server', { lookupUrl, options: lookupOptions });
55+
const { archiveUrl, fileToExtract } = await got(
56+
'https://temporal.download/temporal-test-server/default',
57+
lookupOptions
58+
).json();
5759

58-
if (asset.content_type === 'application/x-gzip' || asset.content_type === 'application/x-gtar') {
60+
console.log('Downloading test server', { archiveUrl, fileToExtract, outputPath });
61+
if (archiveUrl.endsWith('.tar.gz')) {
5962
const extract = tar.extract();
60-
extract.on('entry', (_headers, stream, next) => {
61-
stream.pipe(fs.createWriteStream(outputPath));
63+
extract.on('entry', (headers, stream, next) => {
64+
if (headers.name === fileToExtract) {
65+
stream.pipe(fs.createWriteStream(outputPath));
66+
}
6267
next();
6368
});
64-
await pipeline(
65-
got.stream(asset.browser_download_url, {
66-
headers: {
67-
...defaultHeaders,
68-
},
69-
}),
70-
zlib.createGunzip(),
71-
extract
72-
);
69+
await pipeline(got.stream(archiveUrl, defaultOptions), zlib.createGunzip(), extract);
7370
await fs.promises.chmod(outputPath, 0o755);
74-
} else if (asset.content_type === 'application/zip') {
71+
} else if (archiveUrl.endsWith('.zip')) {
7572
got
76-
.stream(asset.browser_download_url, {
77-
headers: {
78-
...defaultHeaders,
79-
},
80-
})
73+
.stream(archiveUrl, defaultOptions)
8174
.pipe(unzipper.Parse())
8275
.on('entry', (entry) => {
83-
if (entry.type === 'File') {
76+
if (entry.type === 'File' && entry.path === fileToExtract) {
8477
entry.pipe(fs.createWriteStream(outputPath));
8578
} else {
8679
entry.autodrain();
8780
}
8881
});
89-
} else {
90-
throw new Error(`Unexpected content type for Test server download: ${asset.content_type}`);
9182
}

packages/workflow/src/interfaces.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ export enum ChildWorkflowCancellationType {
223223
}
224224

225225
checkExtends<coresdk.child_workflow.ChildWorkflowCancellationType, ChildWorkflowCancellationType>();
226+
checkExtends<ChildWorkflowCancellationType, coresdk.child_workflow.ChildWorkflowCancellationType>();
226227

227228
/**
228229
* How a Child Workflow reacts to the Parent Workflow reaching a Closed state.
@@ -254,6 +255,7 @@ export enum ParentClosePolicy {
254255
}
255256

256257
checkExtends<coresdk.child_workflow.ParentClosePolicy, ParentClosePolicy>();
258+
checkExtends<ParentClosePolicy, coresdk.child_workflow.ParentClosePolicy>();
257259

258260
export interface ChildWorkflowOptions extends CommonWorkflowOptions {
259261
/**

0 commit comments

Comments
 (0)