@iexec/iapp-maker 0.0.1-alpha-nightly-6be476717b877e4857383c375d5f209dbd288f99 → 0.0.1-alpha-nightly-ef579faebe1b4ee041f6da3e79851c51d6dd180e
Sign up to get free protection for your applications and to get access to all the features.
- package/package.json +1 -2
- package/src/cmd/deploy.js +0 -1
- package/src/cmd/run.js +1 -2
- package/src/utils/dockerhub.js +13 -2
- package/src/utils/prepareInputFile.js +1 -4
- package/src/utils/sconify.js +53 -23
- package/src/utils/sleep.js +1 -0
- package/templates/js/package-lock.json +5 -5
- package/templates/js/package.json +1 -1
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@iexec/iapp-maker",
|
3
|
-
"version": "0.0.1-alpha-nightly-
|
3
|
+
"version": "0.0.1-alpha-nightly-ef579faebe1b4ee041f6da3e79851c51d6dd180e",
|
4
4
|
"description": "A CLI to guide you through the process of building an iExec iApp",
|
5
5
|
"main": "src/index.js",
|
6
6
|
"type": "module",
|
@@ -44,7 +44,6 @@
|
|
44
44
|
"magic-bytes.js": "^1.10.0",
|
45
45
|
"ora": "^8.1.1",
|
46
46
|
"prompts": "^2.4.2",
|
47
|
-
"undici": "^6.21.0",
|
48
47
|
"uuid": "^11.0.3",
|
49
48
|
"yargs": "^17.7.2",
|
50
49
|
"zod": "^3.23.8",
|
package/src/cmd/deploy.js
CHANGED
@@ -89,7 +89,6 @@ export async function deploy() {
|
|
89
89
|
'Transforming your image into a TEE image and deploying on iExec, this may take a few minutes...'
|
90
90
|
);
|
91
91
|
const { sconifiedImage, appContractAddress } = await sconify({
|
92
|
-
sconifyForProd: false,
|
93
92
|
iAppNameToSconify: imageTag,
|
94
93
|
walletAddress,
|
95
94
|
dockerhubAccessToken,
|
package/src/cmd/run.js
CHANGED
@@ -133,8 +133,7 @@ export async function runInDebug({
|
|
133
133
|
tag: SCONE_TAG,
|
134
134
|
});
|
135
135
|
const apporder = await iexec.order.signApporder(apporderTemplate);
|
136
|
-
|
137
|
-
spinner.succeed('AppOrder created and published');
|
136
|
+
spinner.succeed('AppOrder created');
|
138
137
|
|
139
138
|
// Dataset Order
|
140
139
|
let datasetorder;
|
package/src/utils/dockerhub.js
CHANGED
@@ -29,6 +29,17 @@ export async function getAuthToken({
|
|
29
29
|
`Fail to get authorization token for scope=${repository}:${action}`
|
30
30
|
);
|
31
31
|
}
|
32
|
-
|
33
|
-
|
32
|
+
return response
|
33
|
+
.json()
|
34
|
+
.catch(() => {
|
35
|
+
throw Error(`Unexpected response from dockerhub auth server`);
|
36
|
+
})
|
37
|
+
.then(({ token }) => {
|
38
|
+
if (!token) {
|
39
|
+
throw Error(
|
40
|
+
`Unexpected response from dockerhub auth server: Missing token`
|
41
|
+
);
|
42
|
+
}
|
43
|
+
return token;
|
44
|
+
});
|
34
45
|
}
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import { mkdir, writeFile } from 'node:fs/promises';
|
2
2
|
import { join } from 'node:path';
|
3
|
-
import { request } from 'undici';
|
4
3
|
import { TEST_INPUT_DIR } from '../config/config.js';
|
5
4
|
|
6
5
|
// TODO we may want to cache to avoid downloading large input files over and over
|
@@ -19,9 +18,7 @@ export async function prepareInputFile(url) {
|
|
19
18
|
if (name === '.' || name === '..') {
|
20
19
|
throw Error('Invalid computed file name');
|
21
20
|
}
|
22
|
-
await
|
23
|
-
throwOnError: true,
|
24
|
-
}).then(async (response) => {
|
21
|
+
await fetch(url).then(async (response) => {
|
25
22
|
await mkdir(TEST_INPUT_DIR, { recursive: true }); // ensure input dir
|
26
23
|
await writeFile(join(TEST_INPUT_DIR, name), response.body);
|
27
24
|
});
|
package/src/utils/sconify.js
CHANGED
@@ -1,19 +1,19 @@
|
|
1
|
-
import { request } from 'undici';
|
2
1
|
import { addDeploymentData } from './cacheExecutions.js';
|
3
2
|
import { SCONIFY_API_URL } from '../config/config.js';
|
4
3
|
import { getAuthToken } from '../utils/dockerhub.js';
|
4
|
+
import { sleep } from './sleep.js';
|
5
|
+
|
6
|
+
const INITIAL_RETRY_PERIOD = 20 * 1000; // 20s
|
7
|
+
|
8
|
+
class TooManyRequestsError extends Error {}
|
5
9
|
|
6
10
|
export async function sconify({
|
7
|
-
sconifyForProd,
|
8
11
|
iAppNameToSconify,
|
9
12
|
walletAddress,
|
10
13
|
dockerhubAccessToken,
|
11
14
|
dockerhubUsername,
|
15
|
+
tryCount = 0,
|
12
16
|
}) {
|
13
|
-
if (sconifyForProd) {
|
14
|
-
throw Error('This feature is not yet implemented. Coming soon ...');
|
15
|
-
}
|
16
|
-
|
17
17
|
let appContractAddress;
|
18
18
|
let sconifiedImage;
|
19
19
|
try {
|
@@ -26,7 +26,7 @@ export async function sconify({
|
|
26
26
|
dockerhubUsername,
|
27
27
|
});
|
28
28
|
|
29
|
-
const
|
29
|
+
const jsonResponse = await fetch(`${SCONIFY_API_URL}/sconify`, {
|
30
30
|
method: 'POST',
|
31
31
|
headers: {
|
32
32
|
'Content-Type': 'application/json',
|
@@ -37,26 +37,56 @@ export async function sconify({
|
|
37
37
|
dockerhubPushToken: pushToken, // used for pushing sconified image on user repo
|
38
38
|
yourWalletPublicAddress: walletAddress,
|
39
39
|
}),
|
40
|
-
|
41
|
-
|
40
|
+
})
|
41
|
+
.catch(() => {
|
42
|
+
throw Error("Can't reach TEE transformation server!");
|
43
|
+
})
|
44
|
+
.then((res) => {
|
45
|
+
if (res.ok) {
|
46
|
+
return res.json().catch(() => {
|
47
|
+
// failed to parse body
|
48
|
+
throw Error('Unexpected server response');
|
49
|
+
});
|
50
|
+
}
|
51
|
+
if (res.status === 429) {
|
52
|
+
throw new TooManyRequestsError(
|
53
|
+
'TEE transformation server is busy, retry later'
|
54
|
+
);
|
55
|
+
}
|
56
|
+
// try getting error message from json body
|
57
|
+
return res
|
58
|
+
.json()
|
59
|
+
.catch(() => {
|
60
|
+
// failed to parse body
|
61
|
+
throw Error('Unknown server error');
|
62
|
+
})
|
63
|
+
.then(({ error }) => {
|
64
|
+
throw Error(error || 'Unknown server error');
|
65
|
+
});
|
66
|
+
});
|
42
67
|
|
43
68
|
// Extract necessary information
|
44
|
-
|
45
|
-
|
46
|
-
|
69
|
+
if (!jsonResponse.appContractAddress) {
|
70
|
+
throw Error('Unexpected server response: missing appContractAddress');
|
71
|
+
}
|
72
|
+
if (!jsonResponse.sconifiedImage) {
|
73
|
+
throw Error('Unexpected server response: missing sconifiedImage');
|
74
|
+
}
|
75
|
+
appContractAddress = jsonResponse.appContractAddress;
|
76
|
+
sconifiedImage = jsonResponse.sconifiedImage;
|
47
77
|
} catch (err) {
|
48
|
-
|
49
|
-
if (err
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
78
|
+
// retry with exponential backoff
|
79
|
+
if (err instanceof TooManyRequestsError && tryCount < 3) {
|
80
|
+
await sleep(INITIAL_RETRY_PERIOD * Math.pow(2, tryCount));
|
81
|
+
return sconify({
|
82
|
+
iAppNameToSconify,
|
83
|
+
walletAddress,
|
84
|
+
dockerhubAccessToken,
|
85
|
+
dockerhubUsername,
|
86
|
+
tryCount: tryCount + 1,
|
87
|
+
});
|
58
88
|
}
|
59
|
-
throw Error(`Failed to transform your app into a TEE app: ${
|
89
|
+
throw Error(`Failed to transform your app into a TEE app: ${err.message}`);
|
60
90
|
}
|
61
91
|
|
62
92
|
// Add deployment data to deployments.json
|
@@ -0,0 +1 @@
|
|
1
|
+
export const sleep = async (ms) => new Promise((res) => setTimeout(res, ms));
|
@@ -1,13 +1,13 @@
|
|
1
1
|
{
|
2
|
-
"name": "hello-world",
|
3
|
-
"version": "
|
2
|
+
"name": "iexec-hello-world-iapp",
|
3
|
+
"version": "0.0.1",
|
4
4
|
"lockfileVersion": 1,
|
5
5
|
"requires": true,
|
6
6
|
"dependencies": {
|
7
7
|
"@iexec/dataprotector-deserializer": {
|
8
|
-
"version": "0.1.
|
9
|
-
"resolved": "https://registry.npmjs.org/@iexec/dataprotector-deserializer/-/dataprotector-deserializer-0.1.
|
10
|
-
"integrity": "sha512-
|
8
|
+
"version": "0.1.1",
|
9
|
+
"resolved": "https://registry.npmjs.org/@iexec/dataprotector-deserializer/-/dataprotector-deserializer-0.1.1.tgz",
|
10
|
+
"integrity": "sha512-CSz1JWnslm2X3gjL1cx/qqovnmvJSFWDyJMw0ZGvqnYnNatgIqHn+Aky2iO4K0HsArfqmgV3ySIpdPfu/N2M0w==",
|
11
11
|
"requires": {
|
12
12
|
"borsh": "^2.0.0",
|
13
13
|
"jszip": "^3.10.1"
|