@suffolklitlab/alkiln 5.4.1-feat-github-server-19 → 5.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/action.yml +10 -33
- package/lib/docassemble/docassemble_api_REST.js +2 -10
- package/lib/docassemble/docassemble_api_interface.js +10 -15
- package/lib/docassemble/get_base_interview_url.js +3 -13
- package/lib/docassemble/setup.js +1 -1
- package/lib/scope.js +34 -19
- package/lib/steps.js +0 -1
- package/lib/utils/log.js +1 -1
- package/lib/utils/session_vars.js +12 -142
- package/package.json +1 -3
- package/setup.py +2 -2
- package/.github/workflows/github_server.yml +0 -77
- package/github_server/action.yml +0 -126
- package/lib/docassemble/server_install.js +0 -40
package/CHANGELOG.md
CHANGED
|
@@ -42,8 +42,14 @@ Format:
|
|
|
42
42
|
### Internal
|
|
43
43
|
-
|
|
44
44
|
-->
|
|
45
|
+
|
|
45
46
|
<!-- ## [Unreleased] -->
|
|
46
47
|
|
|
48
|
+
## [5.4.2] - 2023-10-22
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
- Downloads are now faster! You won't have to wait for the full duration of a step (30 seconds by default) to download a file anymore. See [this PR](https://github.com/SuffolkLITLab/ALKiln/pull/798) for more details.
|
|
52
|
+
|
|
47
53
|
## [5.4.1] - 2023-10-18
|
|
48
54
|
|
|
49
55
|
### Internal
|
package/action.yml
CHANGED
|
@@ -22,15 +22,6 @@ inputs:
|
|
|
22
22
|
description: "Max amount of time to give the server to reload if it needs to"
|
|
23
23
|
required: false
|
|
24
24
|
# no default to let the custom Scenario timeouts create the reload timeout
|
|
25
|
-
# INSTALL_LOCATION? Will that get confused with the location passed into the command line?
|
|
26
|
-
# Maybe `INSTALL_LOCATION` could be "playground", "server", or a custom path and we could handle all those.
|
|
27
|
-
INSTALL_METHOD:
|
|
28
|
-
description: "Default is 'playground'. Other option: 'server'. How to install the package onto the server."
|
|
29
|
-
required: false
|
|
30
|
-
default: "playground"
|
|
31
|
-
ALKILN_TAG_EXPRESSION:
|
|
32
|
-
description: "The tag expression to use to limit which tests to run. Default is no tag expression."
|
|
33
|
-
required: false
|
|
34
25
|
|
|
35
26
|
runs:
|
|
36
27
|
using: "composite"
|
|
@@ -55,43 +46,29 @@ runs:
|
|
|
55
46
|
echo -e "\nALKiln version is $ALKILN_VERSION\nRepo is $REPO_URL\nBranch ref is $BRANCH_PATH\nMAX_SECONDS_FOR_SETUP is $MAX_SECONDS_FOR_SETUP\nSERVER_RELOAD_TIMEOUT_SECONDS is $SERVER_RELOAD_TIMEOUT_SECONDS\n"
|
|
56
47
|
shell: bash
|
|
57
48
|
|
|
58
|
-
# Install
|
|
49
|
+
# Install node
|
|
59
50
|
- name: "ALKiln: Install node packages"
|
|
60
51
|
uses: actions/setup-node@v3
|
|
61
52
|
with:
|
|
62
53
|
node-version: "18"
|
|
63
54
|
- name: Install ALKiln directly from npm
|
|
64
55
|
run: |
|
|
65
|
-
npm install -g @suffolklitlab/alkiln
|
|
56
|
+
npm install -g @suffolklitlab/alkiln
|
|
66
57
|
shell: bash
|
|
67
58
|
|
|
68
|
-
#
|
|
59
|
+
# Run tests
|
|
69
60
|
- name: "ALKiln: Create a Project and pull the package from GitHub"
|
|
70
|
-
if: ${{ inputs.INSTALL_METHOD == 'playground' }}
|
|
71
61
|
run: alkiln-setup
|
|
72
62
|
shell: bash
|
|
73
|
-
- run: echo -e "\n\n====\nALKiln could not create a project on your server's testing account or pull your package into it. Check the messages above this line.\n\n"
|
|
74
|
-
if: ${{ inputs.INSTALL_METHOD == 'playground' && failure() }}
|
|
75
|
-
shell: bash
|
|
76
|
-
|
|
77
|
-
# Install on server
|
|
78
|
-
- name: "ALKiln: Install the GitHub package onto the server"
|
|
79
|
-
if: ${{ inputs.INSTALL_METHOD == 'server' }}
|
|
80
|
-
run: alkiln-server-install
|
|
81
|
-
shell: bash
|
|
82
|
-
- run: echo -e "\n\n====\nALKiln could not install the package on the temporary GitHub docassemble server. Check the steps above this line.\n\n"
|
|
83
|
-
if: ${{ inputs.INSTALL_METHOD == 'server' && failure() }}
|
|
84
|
-
shell: bash
|
|
85
|
-
|
|
86
|
-
# run tests
|
|
87
63
|
- name: "ALKiln: Run tests"
|
|
88
64
|
if: ${{ success() }}
|
|
89
|
-
run: alkiln-run ${{
|
|
65
|
+
run: alkiln-run ${{ github.event.inputs.tags && format('{0}', github.event.inputs.tags) }}
|
|
90
66
|
shell: bash
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
67
|
+
- run: echo -e "\n\n====ALKiln could not create a project on your server's testing account or pull your package into it. Check the messages above this line.\n\n"
|
|
68
|
+
if: ${{ failure() }}
|
|
69
|
+
shell: bash
|
|
70
|
+
- name: "ALKiln: Delete project from docassemble test account"
|
|
71
|
+
if: ${{ always() }}
|
|
95
72
|
run: alkiln-takedown
|
|
96
73
|
shell: bash
|
|
97
74
|
|
|
@@ -104,7 +81,7 @@ runs:
|
|
|
104
81
|
path: ./alkiln-*
|
|
105
82
|
|
|
106
83
|
# ##################################
|
|
107
|
-
# # A developer's workflow should look similar to the below
|
|
84
|
+
# # A developer's workflow should look similar to the below
|
|
108
85
|
# # In place of `uses: suffolkLITLab/ALKiln@v5`, they
|
|
109
86
|
# # might use another version.
|
|
110
87
|
#
|
|
@@ -79,21 +79,13 @@ da.pull = async function ( timeout ) {
|
|
|
79
79
|
}; // Ends da.pull()
|
|
80
80
|
|
|
81
81
|
|
|
82
|
-
da.has_playground_task_finished = async function ( task_id, timeout ) {
|
|
83
|
-
return await da.has_task_finished( "/api/restart_status", task_id, timeout);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
da.has_package_task_finished = async function ( task_id, timeout ) {
|
|
87
|
-
return await da.has_task_finished( "/api/package_update_status", task_id, timeout);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
82
|
// node -e 'require("./lib/docassemble/docassemble_api_REST.js").has_task_finished()'
|
|
91
|
-
da.has_task_finished = async function (
|
|
83
|
+
da.has_task_finished = async function ( task_id, timeout ) {
|
|
92
84
|
/* Check task status based on `task_id`. */
|
|
93
85
|
let options = {
|
|
94
86
|
method: 'GET',
|
|
95
87
|
headers: {'X-API-Key': session_vars.get_dev_api_key()},
|
|
96
|
-
url: `${ session_vars.get_da_server_url() }
|
|
88
|
+
url: `${ session_vars.get_da_server_url() }/api/restart_status`,
|
|
97
89
|
params: {
|
|
98
90
|
task_id: task_id,
|
|
99
91
|
},
|
|
@@ -329,8 +329,9 @@ da_i.pull = async function ( pull_options ) {
|
|
|
329
329
|
}
|
|
330
330
|
}; // Ends da_i.pull()
|
|
331
331
|
|
|
332
|
+
|
|
332
333
|
// node -e 'require("./lib/docassemble/docassemble_api_interface.js").has_task_finished()'
|
|
333
|
-
da_i.has_task_finished = async function (
|
|
334
|
+
da_i.has_task_finished = async function ( task_id, options ) {
|
|
334
335
|
/** Check task status if it exists. If not, return true as task did
|
|
335
336
|
* not require a server restart. See da_i.pull().
|
|
336
337
|
* See https://docassemble.org/docs/api.html#restart_status. */
|
|
@@ -341,7 +342,7 @@ da_i.has_task_finished = async function ( api_endpoint, task_id, options ) {
|
|
|
341
342
|
try {
|
|
342
343
|
|
|
343
344
|
// If server did need to restart, check if it's done.
|
|
344
|
-
let response = await _da_REST.has_task_finished(
|
|
345
|
+
let response = await _da_REST.has_task_finished( task_id, timeout );
|
|
345
346
|
log.debug({ pre: `Task status: ${ response.status }. Docassemble status text: ${ response.data.status }. Task id: ${ task_id }` });
|
|
346
347
|
|
|
347
348
|
if ( response.data.status === 'completed' ) {
|
|
@@ -352,15 +353,16 @@ da_i.has_task_finished = async function ( api_endpoint, task_id, options ) {
|
|
|
352
353
|
return false;
|
|
353
354
|
|
|
354
355
|
} else if ( response.data.status === 'unknown' ) {
|
|
355
|
-
// Server is working, but status 'unknown'?
|
|
356
|
-
//
|
|
356
|
+
// Server is working, but status 'unknown'? We shouldn't even
|
|
357
|
+
// get here according to the API docs, but it feels weird to have
|
|
358
|
+
// no default behavior. What to return? Throw?
|
|
357
359
|
log.info({
|
|
358
360
|
pre: `\`task_id\` "${ task_id }" has expired. If it's been `
|
|
359
361
|
+ `less than 1 hour since the task started, the task is `
|
|
360
362
|
+ `complete. See https://docassemble.org/docs/api.html#restart_status.`,
|
|
361
|
-
data: response
|
|
363
|
+
data: response,
|
|
362
364
|
});
|
|
363
|
-
return
|
|
365
|
+
return null;
|
|
364
366
|
} // ends status type
|
|
365
367
|
|
|
366
368
|
} catch ( error ) {
|
|
@@ -376,15 +378,8 @@ da_i.has_task_finished = async function ( api_endpoint, task_id, options ) {
|
|
|
376
378
|
|
|
377
379
|
}; // Ends da_i.has_task_finished()
|
|
378
380
|
|
|
379
|
-
da_i.wait_for_playground_to_restart = async ( task_id, options ) => {
|
|
380
|
-
return await da_i.wait_for_server_to_restart( "/api/restart_status", task_id, options );
|
|
381
|
-
};
|
|
382
|
-
|
|
383
|
-
da_i.wait_for_package_to_restart = async ( task_id, options ) => {
|
|
384
|
-
return await da_i.wait_for_server_to_restart( "/api/package_update_status", task_id, options );
|
|
385
|
-
};
|
|
386
381
|
|
|
387
|
-
da_i.wait_for_server_to_restart = async (
|
|
382
|
+
da_i.wait_for_server_to_restart = async ( task_id, options ) => {
|
|
388
383
|
/** Wait for the server to finish restarting in case a module needs to load.
|
|
389
384
|
* This is a polling function because things may be returned
|
|
390
385
|
* that aren't equivalent to the server being done with a task. */
|
|
@@ -415,7 +410,7 @@ da_i.wait_for_server_to_restart = async ( api_endpoint, task_id, options ) => {
|
|
|
415
410
|
while ( !done_restarting && num_tries <= max_loops ) {
|
|
416
411
|
num_tries++;
|
|
417
412
|
// Wait only a short time for the task to finish, not the full default timeout
|
|
418
|
-
done_restarting = await da_i.has_task_finished(
|
|
413
|
+
done_restarting = await da_i.has_task_finished( task_id, { timeout: wait_for_response } );
|
|
419
414
|
if ( !done_restarting ) {
|
|
420
415
|
if ( num_tries < max_loops ) {
|
|
421
416
|
// Show a slightly different message after a number of tries to reassure
|
|
@@ -10,20 +10,10 @@ let get_base_interview_url = async function () {
|
|
|
10
10
|
* When finishing a test, we go to the sign out page (which is supposed to help even
|
|
11
11
|
* when the user is not logged in.) We can't use `reset=2` because it caused an
|
|
12
12
|
* 'Unable to locate interview session' error. */
|
|
13
|
-
|
|
14
13
|
let server_url = session_vars.get_da_server_url();
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return `${ server_url }/interview?new_session=1&i=docassemble.${session_vars.get_repo_folder_name()}%3Adata/questions/`;
|
|
19
|
-
|
|
20
|
-
} else {
|
|
21
|
-
|
|
22
|
-
let dev_id = await docassemble_api_interface.get_dev_id();
|
|
23
|
-
let project_name = session_vars.get_project_name();
|
|
24
|
-
return `${ server_url }/interview?new_session=1&i=docassemble.playground${ dev_id }${ project_name }%3A`;
|
|
25
|
-
|
|
26
|
-
}
|
|
14
|
+
let dev_id = await docassemble_api_interface.get_dev_id();
|
|
15
|
+
let project_name = session_vars.get_project_name();
|
|
16
|
+
return `${ server_url }/interview?new_session=1&i=docassemble.playground${ dev_id }${ project_name }%3A`;
|
|
27
17
|
};
|
|
28
18
|
|
|
29
19
|
module.exports = get_base_interview_url;
|
package/lib/docassemble/setup.js
CHANGED
|
@@ -39,7 +39,7 @@ const setup = async () => {
|
|
|
39
39
|
let task_id = await da_i.pull();
|
|
40
40
|
// Task id will be null if server did not need to restart
|
|
41
41
|
if ( task_id ) {
|
|
42
|
-
await da_i.
|
|
42
|
+
await da_i.wait_for_server_to_restart( task_id );
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
// Finish
|
package/lib/scope.js
CHANGED
|
@@ -46,9 +46,6 @@ let printable_var_value = function(row) {
|
|
|
46
46
|
/* `row` might be a row, a source row, or an original row. */
|
|
47
47
|
let original = get_original_row(row);
|
|
48
48
|
if ( is_secret_var(original) ) {
|
|
49
|
-
if ( session_vars.get_dangerous_debug() ) {
|
|
50
|
-
return `alkiln_dangerous ${ row.value }`;
|
|
51
|
-
}
|
|
52
49
|
return original.flags.secret_name;
|
|
53
50
|
}
|
|
54
51
|
return row.value;
|
|
@@ -2440,10 +2437,6 @@ module.exports = {
|
|
|
2440
2437
|
/** Sets a non-story table variable to a "secret" value (i.e. an env var) */
|
|
2441
2438
|
// Prevent pictures of a screen with a secret.
|
|
2442
2439
|
scope.disable_error_screenshot = true;
|
|
2443
|
-
if ( session_vars.get_dangerous_debug() ) {
|
|
2444
|
-
scope.disable_error_screenshot = false;
|
|
2445
|
-
}
|
|
2446
|
-
|
|
2447
2440
|
let var_data = await scope.normalizeTable( scope, {
|
|
2448
2441
|
var_data: [{
|
|
2449
2442
|
var: var_name,
|
|
@@ -2492,10 +2485,39 @@ module.exports = {
|
|
|
2492
2485
|
if ( !elem ) { reports.addToReport(scope, { type: `error`, value: msg }); }
|
|
2493
2486
|
expect( elem, msg ).to.exist;
|
|
2494
2487
|
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2488
|
+
let failed_to_download = false;
|
|
2489
|
+
let err_msg = "";
|
|
2490
|
+
try {
|
|
2491
|
+
const binaryStr = await scope.page.evaluate(el => {
|
|
2492
|
+
const url = el.getAttribute("href");
|
|
2493
|
+
return new Promise(async (resolve, reject) => {
|
|
2494
|
+
const response = await fetch(url, {method: "GET"});
|
|
2495
|
+
const reader = new FileReader();
|
|
2496
|
+
reader.readAsBinaryString(await response.blob());
|
|
2497
|
+
reader.onload = () => resolve(reader.result);
|
|
2498
|
+
reader.onerror = () => reject(`Error occurred on page when downloading ${ url }: ${ reader.error }`);
|
|
2499
|
+
});
|
|
2500
|
+
}, elem);
|
|
2501
|
+
if (binaryStr !== '') {
|
|
2502
|
+
const fileData = Buffer.from(binaryStr, 'binary');
|
|
2503
|
+
fs.writeFileSync(`${ scope.paths.scenario }/${ filename }`, fileData);
|
|
2504
|
+
reports.addToReport(scope, { type: `info`, value: `Downloaded ${ filename } (${ fileData.length } bytes) to ${ scope.paths.scenario }`});
|
|
2505
|
+
} else {
|
|
2506
|
+
failed_to_download = true;
|
|
2507
|
+
err_msg = `Couldn't download ${ filename }, binary data for download was empty`;
|
|
2508
|
+
}
|
|
2509
|
+
} catch (error) {
|
|
2510
|
+
failed_to_download = true;
|
|
2511
|
+
err_msg = error;
|
|
2512
|
+
}
|
|
2513
|
+
|
|
2514
|
+
if (failed_to_download) {
|
|
2515
|
+
reports.addToReport(scope, { type: `warning`, value: `Could not download file using fetch (${ err_msg }). ALKiln will now fallback to the click download method` });
|
|
2516
|
+
scope.toDownload = filename;
|
|
2517
|
+
// Should this be using `scope.tapElement()`?
|
|
2518
|
+
await elem.evaluate( elem => { return elem.click(); });
|
|
2519
|
+
await scope.detectDownloadComplete( scope );
|
|
2520
|
+
}
|
|
2499
2521
|
}, // Ends scope.steps.download()
|
|
2500
2522
|
|
|
2501
2523
|
compare_pdfs: async function (scope, {existing_pdf_path, new_pdf_path}) {
|
|
@@ -2613,10 +2635,7 @@ module.exports = {
|
|
|
2613
2635
|
*/
|
|
2614
2636
|
// Don't take a picture of a failed login in case one of the inputs is correct
|
|
2615
2637
|
scope.disable_error_screenshot = true;
|
|
2616
|
-
|
|
2617
|
-
scope.disable_error_screenshot = false;
|
|
2618
|
-
}
|
|
2619
|
-
|
|
2638
|
+
|
|
2620
2639
|
// If there is no browser open, start a new one
|
|
2621
2640
|
if (!scope.browser) {
|
|
2622
2641
|
scope.browser = await scope.driver.launch({ headless: !session_vars.DEBUG });
|
|
@@ -2649,10 +2668,6 @@ module.exports = {
|
|
|
2649
2668
|
let email = process.env[ email_secret_name ];
|
|
2650
2669
|
let password = process.env[ password_secret_name ];
|
|
2651
2670
|
|
|
2652
|
-
if ( session_vars.get_dangerous_debug() ) {
|
|
2653
|
-
log.debug({ type: `unsafe`, data: `login: ${ email }, ${ password }` });
|
|
2654
|
-
}
|
|
2655
|
-
|
|
2656
2671
|
// Give as many useful messages to the user as possible if the env vars
|
|
2657
2672
|
// aren't defined. Eventually, just provide a link to the docs because
|
|
2658
2673
|
// this is complex
|
package/lib/steps.js
CHANGED
|
@@ -203,7 +203,6 @@ Given(/I start the interview at "([^"]+)"/, {timeout: -1}, async (file_name) =>
|
|
|
203
203
|
scope.page.on('response', async response => {
|
|
204
204
|
// Note: We can expect that only one file will be getting downloaded
|
|
205
205
|
// at any one time since each step completes synchronously
|
|
206
|
-
|
|
207
206
|
// If response has a file in it that matches the file we are downloading
|
|
208
207
|
// Sadly, 'content-disposition' isn't working. We're not sure what will.
|
|
209
208
|
if ( response.headers()['content-disposition'] && (response.headers()['content-disposition']).includes(`attachment;filename=${scope.toDownload}`) ) {
|
package/lib/utils/log.js
CHANGED
|
@@ -42,7 +42,7 @@ log.error = function ({ type='', pre='', data='', post='' }) {
|
|
|
42
42
|
|
|
43
43
|
log.debug = function ({ type='', pre='', data='', post='' }) {
|
|
44
44
|
/* If debugging is turned on, log a message that includes `ALKiln` and `debug` */
|
|
45
|
-
if ( session_vars.get_debug()
|
|
45
|
+
if ( session_vars.get_debug() ) {
|
|
46
46
|
let start = create_msg_start([ type, 'debug' ], pre );
|
|
47
47
|
// Log them each on a separate line
|
|
48
48
|
console.log( `ALKiln ${ type } debug: ${ pre }` );
|
|
@@ -24,11 +24,6 @@ module.exports = session_vars;
|
|
|
24
24
|
// These default to null
|
|
25
25
|
// TODO: How to isolate debug elsewhere so this file can use the logger?
|
|
26
26
|
session_vars.get_debug = function () { return process.env.DEBUG || null; };
|
|
27
|
-
session_vars.get_dangerous_debug = function () {
|
|
28
|
-
/** Note this will cause failure of tests that reassure the user about
|
|
29
|
-
* security precautions we took, like not taking a screenshot. */
|
|
30
|
-
return process.env._ALKILN_DANGEROUS_DEBUG || null;
|
|
31
|
-
};
|
|
32
27
|
session_vars.is_dev_env = function () { return process.env.DEV || null; }
|
|
33
28
|
|
|
34
29
|
session_vars.get_dev_api_key = function () { return process.env.DOCASSEMBLE_DEVELOPER_API_KEY || null; };
|
|
@@ -178,120 +173,8 @@ session_vars.delete_project_name = function () {
|
|
|
178
173
|
const artifacts_path_key = `artifacts_path`;
|
|
179
174
|
session_vars.save_artifacts_path_name = function ( path_name ) {
|
|
180
175
|
/* Save a key with the name of the current artifacts folder in case it doesn't exist. */
|
|
181
|
-
return session_vars.save_runtime_config_var({ key: artifacts_path_key, value: path_name });
|
|
182
|
-
|
|
183
|
-
// // Ensure artifacts path file exists
|
|
184
|
-
// if ( !fs.existsSync( runtime_config_path ) ) {
|
|
185
|
-
// // If the file doesn't exist, make one because next we need to read it
|
|
186
|
-
// fs.writeFileSync( runtime_config_path, JSON.stringify( {}, null, 2 ) );
|
|
187
|
-
// }
|
|
188
|
-
|
|
189
|
-
// // Get the json, changing it, and re-write the file from scratch
|
|
190
|
-
// let json = JSON.parse( fs.readFileSync( runtime_config_path ) );
|
|
191
|
-
// json[ artifacts_path_key ] = path_name;
|
|
192
|
-
// let file = fs.writeFileSync( runtime_config_path, JSON.stringify( json, null, 2 ) );
|
|
193
|
-
|
|
194
|
-
// if ( session_vars.get_debug() ) {
|
|
195
|
-
// console.log( `ALKiln debug: Stored name of artifacts directory "${ path_name }" locally.` );
|
|
196
|
-
// }
|
|
197
|
-
// return file;
|
|
198
|
-
}; // Ends save_artifacts_path_name()
|
|
199
|
-
|
|
200
|
-
session_vars.get_artifacts_path_name = function () {
|
|
201
|
-
/* Get the name of the current artifacts path. */
|
|
202
|
-
return session_vars.get_runtime_config_var( artifacts_path_key );
|
|
203
|
-
// try {
|
|
204
|
-
// let json = JSON.parse( fs.readFileSync( runtime_config_path ));
|
|
205
|
-
// let path_name = json[ artifacts_path_key ];
|
|
206
|
-
|
|
207
|
-
// if ( session_vars.get_debug() ) { console.log( `ALKiln debug: Artifacts directory is "${ path_name }".` ); }
|
|
208
|
-
// return path_name;
|
|
209
|
-
// } catch ( error ) {
|
|
210
|
-
// return null;
|
|
211
|
-
// }
|
|
212
|
-
}; // Ends get_artifacts_path_name()
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
const install_method_key = `da_install_method`;
|
|
216
|
-
session_vars.save_install_method = function (install_method) {
|
|
217
|
-
/* Save a key with the name of the current artifacts folder in case it doesn't exist. */
|
|
218
|
-
return session_vars.save_runtime_config_var({ key: install_method_key, value: install_method });
|
|
219
|
-
|
|
220
|
-
// // Ensure artifacts path file exists
|
|
221
|
-
// if ( !fs.existsSync( runtime_config_path ) ) {
|
|
222
|
-
// // If the file doesn't exist, make one because next we need to read it
|
|
223
|
-
// fs.writeFileSync( runtime_config_path, JSON.stringify( {}, null, 2 ) );
|
|
224
|
-
// }
|
|
225
|
-
|
|
226
|
-
// // Get the json, changing it, and re-write the file from scratch
|
|
227
|
-
// let json = JSON.parse( fs.readFileSync( runtime_config_path ) );
|
|
228
|
-
// json[ install_method_key ] = install_method;
|
|
229
|
-
// let file = fs.writeFileSync( runtime_config_path, JSON.stringify( json, null, 2 ) );
|
|
230
|
-
|
|
231
|
-
// return file;
|
|
232
|
-
}; // Ends save_install_method()
|
|
233
|
-
|
|
234
|
-
session_vars.get_install_method = function () {
|
|
235
|
-
/* Get the name of the current install method. */
|
|
236
|
-
return session_vars.get_runtime_config_var( install_method_key );
|
|
237
|
-
// try {
|
|
238
|
-
// let json = JSON.parse( fs.readFileSync( runtime_config_path ));
|
|
239
|
-
// let install_method = json[ install_method_key ];
|
|
240
|
-
|
|
241
|
-
// return install_method;
|
|
242
|
-
// } catch ( error ) {
|
|
243
|
-
// return null;
|
|
244
|
-
// }
|
|
245
|
-
}; // Ends get_install_method()
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
const repo_folder_key = `da_repo_folder_name`;
|
|
249
|
-
session_vars.save_repo_folder_name = function (repo_folder_name) {
|
|
250
|
-
/** Save a key with the name of the main package folder in the repository. */
|
|
251
|
-
return session_vars.save_runtime_config_var({ key: repo_folder_key, value: repo_folder_name });
|
|
252
|
-
|
|
253
|
-
// // Ensure runtime config file exists
|
|
254
|
-
// if ( !fs.existsSync( runtime_config_path ) ) {
|
|
255
|
-
// // If the file doesn't exist, make one because next we need to read it
|
|
256
|
-
// fs.writeFileSync( runtime_config_path, JSON.stringify( {}, null, 2 ) );
|
|
257
|
-
// }
|
|
258
|
-
|
|
259
|
-
// // Get the json, changing it, and re-write the file from scratch
|
|
260
|
-
// let json = JSON.parse( fs.readFileSync( runtime_config_path ) );
|
|
261
|
-
// json[ repo_folder_key ] = repo_folder_name;
|
|
262
|
-
// let file = fs.writeFileSync( runtime_config_path, JSON.stringify( json, null, 2 ) );
|
|
263
|
-
|
|
264
|
-
// return file;
|
|
265
|
-
}; // Ends session_vars.save_repo_folder_name()
|
|
266
|
-
|
|
267
|
-
session_vars.get_repo_folder_name = function () {
|
|
268
|
-
/** Get the name of the main folder in the repository. */
|
|
269
|
-
return session_vars.get_runtime_config_var( repo_folder_key );
|
|
270
|
-
// try {
|
|
271
|
-
// let json = JSON.parse( fs.readFileSync( runtime_config_path ));
|
|
272
|
-
// let name = json[ repo_folder_key ];
|
|
273
|
-
|
|
274
|
-
// return name;
|
|
275
|
-
// } catch ( error ) {
|
|
276
|
-
// return null;
|
|
277
|
-
// }
|
|
278
|
-
}; // Ends session_vars.get_repo_folder_name()
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
// TODO: Should we replace the other method calls with this one?
|
|
282
|
-
// i.e. `save_repo_folder_name`, etc. It would clarify exactly
|
|
283
|
-
// what those calls are doing, but would lock in implementation
|
|
284
|
-
session_vars.save_runtime_config_var = function ({ key, value }) {
|
|
285
|
-
/** Write to the runtime config file by adding a key/value pair to
|
|
286
|
-
* the json object there.
|
|
287
|
-
*
|
|
288
|
-
* @param key {str} Key to use to store `value` in runtime config file
|
|
289
|
-
* @param value {any} Value to store in runtime config file
|
|
290
|
-
*
|
|
291
|
-
* @returns file {binary?} Runtime config file
|
|
292
|
-
*/
|
|
293
176
|
|
|
294
|
-
// Ensure
|
|
177
|
+
// Ensure artifacts path file exists
|
|
295
178
|
if ( !fs.existsSync( runtime_config_path ) ) {
|
|
296
179
|
// If the file doesn't exist, make one because next we need to read it
|
|
297
180
|
fs.writeFileSync( runtime_config_path, JSON.stringify( {}, null, 2 ) );
|
|
@@ -299,35 +182,27 @@ session_vars.save_runtime_config_var = function ({ key, value }) {
|
|
|
299
182
|
|
|
300
183
|
// Get the json, changing it, and re-write the file from scratch
|
|
301
184
|
let json = JSON.parse( fs.readFileSync( runtime_config_path ) );
|
|
302
|
-
json[
|
|
185
|
+
json[ artifacts_path_key ] = path_name;
|
|
303
186
|
let file = fs.writeFileSync( runtime_config_path, JSON.stringify( json, null, 2 ) );
|
|
304
187
|
|
|
305
188
|
if ( session_vars.get_debug() ) {
|
|
306
|
-
console.log( `ALKiln debug
|
|
189
|
+
console.log( `ALKiln debug: Stored name of artifacts directory "${ path_name }" locally.` );
|
|
307
190
|
}
|
|
308
191
|
return file;
|
|
309
|
-
}; // Ends
|
|
192
|
+
}; // Ends save_artifacts_path_name()
|
|
310
193
|
|
|
311
|
-
session_vars.
|
|
312
|
-
|
|
313
|
-
*
|
|
314
|
-
* @param key {str} Key in runtime config file that contains the desired value
|
|
315
|
-
* @returns value | null {any} Value of key in runtime config file. If it
|
|
316
|
-
* doesn't exist, returns null.
|
|
317
|
-
*/
|
|
194
|
+
session_vars.get_artifacts_path_name = function () {
|
|
195
|
+
/* Get the name of the current artifacts path. */
|
|
318
196
|
try {
|
|
319
197
|
let json = JSON.parse( fs.readFileSync( runtime_config_path ));
|
|
320
|
-
let
|
|
321
|
-
if ( session_vars.get_debug() ) {
|
|
322
|
-
console.log( `ALKiln debug runtime config var: "${key}"" is "${value}".` );
|
|
323
|
-
}
|
|
198
|
+
let path_name = json[ artifacts_path_key ];
|
|
324
199
|
|
|
325
|
-
|
|
200
|
+
if ( session_vars.get_debug() ) { console.log( `ALKiln debug: Artifacts directory is "${ path_name }".` ); }
|
|
201
|
+
return path_name;
|
|
326
202
|
} catch ( error ) {
|
|
327
203
|
return null;
|
|
328
204
|
}
|
|
329
|
-
}; // Ends
|
|
330
|
-
|
|
205
|
+
}; // Ends get_artifacts_path_name()
|
|
331
206
|
|
|
332
207
|
session_vars.set_sources_paths = function ( paths ) {
|
|
333
208
|
/** Returns whether at least one of the given path exists. Store
|
|
@@ -360,7 +235,7 @@ session_vars.set_sources_paths = function ( paths ) {
|
|
|
360
235
|
// Warn about missing paths
|
|
361
236
|
if ( missing_paths.length > 0 ) {
|
|
362
237
|
console.warn(
|
|
363
|
-
`ALKiln WARNING: ALKiln can't find folders at "${ paths.join(
|
|
238
|
+
`ALKiln WARNING: ALKiln can't find folders at "${ paths.join(", ") }".`
|
|
364
239
|
);
|
|
365
240
|
}
|
|
366
241
|
|
|
@@ -370,14 +245,10 @@ session_vars.set_sources_paths = function ( paths ) {
|
|
|
370
245
|
return false;
|
|
371
246
|
}
|
|
372
247
|
|
|
373
|
-
console.info(
|
|
374
|
-
`ALKiln info: Did find "sources" folder(s) at "${ existing_paths.join('", "') }".`
|
|
375
|
-
)
|
|
376
|
-
|
|
377
248
|
// Otherwise, store valid paths
|
|
378
249
|
session_vars._sources_paths = existing_paths;
|
|
379
250
|
return true;
|
|
380
|
-
};
|
|
251
|
+
};
|
|
381
252
|
|
|
382
253
|
session_vars.get_sources_paths = function () {
|
|
383
254
|
/** Get the "sources" folder path. Should never be undefined during
|
|
@@ -388,7 +259,6 @@ session_vars.get_sources_paths = function () {
|
|
|
388
259
|
return session_vars._sources_paths;
|
|
389
260
|
};
|
|
390
261
|
|
|
391
|
-
|
|
392
262
|
session_vars.validateEnvironment = function() {
|
|
393
263
|
/** Throw a useful error for the developer if any of the env vars
|
|
394
264
|
* required by absolutely all tests are missing. Gather all
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suffolklitlab/alkiln",
|
|
3
|
-
"version": "5.4.
|
|
3
|
+
"version": "5.4.2",
|
|
4
4
|
"description": "Integrated automated end-to-end testing with docassemble, puppeteer, and cucumber.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
"local": "npm run setup && npm run cucumber; npm run takedown",
|
|
10
10
|
"setup": "./lib/docassemble/setup.js",
|
|
11
11
|
"takedown": "./lib/docassemble/takedown.js",
|
|
12
|
-
"server_install": "./lib/docassemble/server_install.js",
|
|
13
12
|
"unit": "mocha tests/unit_tests/*.test.*"
|
|
14
13
|
},
|
|
15
14
|
"repository": {
|
|
@@ -51,7 +50,6 @@
|
|
|
51
50
|
"diff": "5.0.0"
|
|
52
51
|
},
|
|
53
52
|
"bin": {
|
|
54
|
-
"alkiln-server-install": "./lib/docassemble/server_install.js",
|
|
55
53
|
"alkiln-setup": "./lib/docassemble/setup.js",
|
|
56
54
|
"alkiln-takedown": "./lib/docassemble/takedown.js",
|
|
57
55
|
"alkiln-run": "./lib/run_cucumber.js"
|
package/setup.py
CHANGED
|
@@ -50,10 +50,10 @@ setup(name='docassemble.ALKilnTests',
|
|
|
50
50
|
author='plocket',
|
|
51
51
|
author_email='example@example.com',
|
|
52
52
|
license='The MIT License (MIT)',
|
|
53
|
-
url='https://suffolklitlab.org/docassemble-AssemblyLine-documentation/docs/
|
|
53
|
+
url='https://suffolklitlab.org/docassemble-AssemblyLine-documentation/docs/automated_integrated_testing',
|
|
54
54
|
packages=find_packages(),
|
|
55
55
|
namespace_packages=['docassemble'],
|
|
56
|
-
install_requires=['docassemble.ALToolbox>=0.
|
|
56
|
+
install_requires=['docassemble.ALToolbox>=0.5.1'],
|
|
57
57
|
zip_safe=False,
|
|
58
58
|
package_data=find_package_data(where='docassemble/ALKilnTests/', package='docassemble.ALKilnTests'),
|
|
59
59
|
)
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
name: GitHub server tests
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
workflow_dispatch:
|
|
6
|
-
inputs:
|
|
7
|
-
tags:
|
|
8
|
-
required: False
|
|
9
|
-
description: 'Optional. Use a "tag expression" specify which tagged tests to run (https://cucumber.io/docs/cucumber/api/#tag-expressions)'
|
|
10
|
-
enable_tmate:
|
|
11
|
-
type: boolean
|
|
12
|
-
description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'
|
|
13
|
-
required: false
|
|
14
|
-
default: false
|
|
15
|
-
# TODO: alkiln_version:
|
|
16
|
-
|
|
17
|
-
jobs:
|
|
18
|
-
|
|
19
|
-
github-server-tests:
|
|
20
|
-
runs-on: ubuntu-latest
|
|
21
|
-
strategy:
|
|
22
|
-
matrix:
|
|
23
|
-
node-version: [18.x]
|
|
24
|
-
|
|
25
|
-
env:
|
|
26
|
-
# TODO: Must solve - how would a dev make another user/password if they wanted to?
|
|
27
|
-
SECRET_VAR1: secret-var1-value
|
|
28
|
-
SECRET_VAR2: secret-var2-value
|
|
29
|
-
SECRET_FOR_MISSING_FIELD: secret for missing field
|
|
30
|
-
|
|
31
|
-
steps:
|
|
32
|
-
# Place the root directory in this branch
|
|
33
|
-
- uses: actions/checkout@v3
|
|
34
|
-
|
|
35
|
-
# Debugging. Maybe add a long sleep after whatever it is we want to check
|
|
36
|
-
# to give us time to explore.
|
|
37
|
-
- name: Setup tmate session
|
|
38
|
-
if: ${{ inputs.enable_tmate }}
|
|
39
|
-
uses: mxschmitt/action-tmate@v3
|
|
40
|
-
with:
|
|
41
|
-
detached: true
|
|
42
|
-
|
|
43
|
-
- name: Start the temporary GitHub server
|
|
44
|
-
id: github_server
|
|
45
|
-
uses: ./github_server
|
|
46
|
-
with:
|
|
47
|
-
CONFIG_CONTENTS: "${{ secrets.CONFIG_CONTENTS }}"
|
|
48
|
-
- run: echo "Finished starting the GitHub server"
|
|
49
|
-
|
|
50
|
-
# Debugging on failure
|
|
51
|
-
# Trying to catch that intermittent bug mentioned in ./github_server/action.yml
|
|
52
|
-
- name: Docker failure tmate session
|
|
53
|
-
if: ${{ failure() }}
|
|
54
|
-
uses: mxschmitt/action-tmate@v3
|
|
55
|
-
|
|
56
|
-
- name: Env vars from server output
|
|
57
|
-
run: |
|
|
58
|
-
echo "USER1_EMAIL=${{ steps.github_server.outputs.DA_ADMIN_EMAIL }}" >> $GITHUB_ENV
|
|
59
|
-
echo "USER1_PASSWORD=${{ steps.github_server.outputs.DA_ADMIN_PASSWORD }}" >> $GITHUB_ENV
|
|
60
|
-
## Example of working with the docker container after it's been started
|
|
61
|
-
#- name: Work with docker
|
|
62
|
-
# run: |
|
|
63
|
-
# container_name=$(docker ps --format '{{.Names}}' | head -n 1)
|
|
64
|
-
# echo "container_name is $container_name"
|
|
65
|
-
|
|
66
|
-
- name: "Run ALKiln tests"
|
|
67
|
-
if: ${{ success() }}
|
|
68
|
-
uses: ./
|
|
69
|
-
with:
|
|
70
|
-
SERVER_URL: "${{ steps.github_server.outputs.SERVER_URL }}"
|
|
71
|
-
DOCASSEMBLE_DEVELOPER_API_KEY: "${{ steps.github_server.outputs.DOCASSEMBLE_DEVELOPER_API_KEY }}"
|
|
72
|
-
INSTALL_METHOD: "server"
|
|
73
|
-
# TODO: See what happens if this is an empty string
|
|
74
|
-
ALKILN_VERSION: "server"
|
|
75
|
-
#ALKILN_TAG_EXPRESSION: "@al1"
|
|
76
|
-
- run: echo "Finished running ALKiln tests"
|
|
77
|
-
|
package/github_server/action.yml
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
name: "ALKiln/github_server: Isolated docassemble tests"
|
|
2
|
-
description: "Download and start up a temporary docassemble server on GitHub's servers, in an isolated environment. Avoids docassemble reload errors and other external factors."
|
|
3
|
-
|
|
4
|
-
# If we want to control the version of the docassemble image, we'd have
|
|
5
|
-
# to make our own image:
|
|
6
|
-
# You can build your own image by doing git clone jhpyle/docassemble and then
|
|
7
|
-
# using git checkout to select a particular version, and then using docker build
|
|
8
|
-
# to build an image. https://docassemble.org/docs/docker.html#downgrading
|
|
9
|
-
# If we just want to use an older version of da (as long as it works with
|
|
10
|
-
# the latest image):
|
|
11
|
-
# If you have an existing container you can use dainstall from the command
|
|
12
|
-
# line to install docassemble.webapp==1.4.68
|
|
13
|
-
|
|
14
|
-
inputs:
|
|
15
|
-
CONFIG_CONTENTS:
|
|
16
|
-
description: "The contents of the config file of the docassemble server"
|
|
17
|
-
required: false
|
|
18
|
-
MAX_SECONDS_FOR_DOCKER:
|
|
19
|
-
description: "Maximum amount of seconds to give the docassemble docker container to serve the site."
|
|
20
|
-
required: false
|
|
21
|
-
default: 600 # 10 min
|
|
22
|
-
|
|
23
|
-
outputs:
|
|
24
|
-
DOCASSEMBLE_DEVELOPER_API_KEY:
|
|
25
|
-
description: "Use this inside `with:` for the ALKiln step. Temporary admin api key. It will be destroyed after the tests are done."
|
|
26
|
-
value: ${{ steps.api_key_output_step.outputs.DOCASSEMBLE_DEVELOPER_API_KEY }}
|
|
27
|
-
SERVER_URL:
|
|
28
|
-
description: "Use this inside `with:` for the ALKiln step. URL of the temporary docassemble server."
|
|
29
|
-
value: "http://localhost"
|
|
30
|
-
DA_ADMIN_EMAIL:
|
|
31
|
-
value: ${{ steps.api_key_output_step.outputs.DA_ADMIN_EMAIL }}
|
|
32
|
-
DA_ADMIN_PASSWORD:
|
|
33
|
-
value: ${{ steps.api_key_output_step.outputs.DA_ADMIN_PASSWORD }}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
runs:
|
|
37
|
-
using: "composite"
|
|
38
|
-
steps:
|
|
39
|
-
- uses: actions/checkout@v3
|
|
40
|
-
|
|
41
|
-
- name: "ALKiln github_server: Set environment variables"
|
|
42
|
-
run: |
|
|
43
|
-
echo "DA_ADMIN_API_KEY=abcd1234abcd1234abcd5678abdc5678" >> $GITHUB_ENV
|
|
44
|
-
echo "MAX_SECONDS_FOR_DOCKER=${{ inputs.MAX_SECONDS_FOR_DOCKER }}" >> $GITHUB_ENV
|
|
45
|
-
echo "DA_ADMIN_EMAIL=admin@example.com" >> $GITHUB_ENV
|
|
46
|
-
# Login will fail if this is "password"
|
|
47
|
-
echo "DA_ADMIN_PASSWORD=@123abcdefg" >> $GITHUB_ENV
|
|
48
|
-
shell: bash
|
|
49
|
-
- id: api_key_output_step
|
|
50
|
-
run: |
|
|
51
|
-
echo "DOCASSEMBLE_DEVELOPER_API_KEY=$DA_ADMIN_API_KEY" >> "$GITHUB_OUTPUT"
|
|
52
|
-
echo "DA_ADMIN_EMAIL=$DA_ADMIN_EMAIL" >> "$GITHUB_OUTPUT"
|
|
53
|
-
echo "DA_ADMIN_PASSWORD=$DA_ADMIN_PASSWORD" >> "$GITHUB_OUTPUT"
|
|
54
|
-
shell: bash
|
|
55
|
-
|
|
56
|
-
- name: "ALKiln github_server: Download and start docker"
|
|
57
|
-
run: |
|
|
58
|
-
mkdir /tmp/config
|
|
59
|
-
echo "${{ inputs.CONFIG_CONTENTS }}" > /tmp/config/myconfig.yml
|
|
60
|
-
docker pull jhpyle/docassemble
|
|
61
|
-
docker run --name docassemble_container --env DA_ADMIN_EMAIL="${{ env.DA_ADMIN_EMAIL }}" --env DA_ADMIN_PASSWORD="${{ env.DA_ADMIN_PASSWORD }}" --env DA_ADMIN_API_KEY="${{ env.DA_ADMIN_API_KEY }}" --env DA_CONFIG=/tmp/config/myconfig.yml --volume /tmp/config:/tmp/config --cap-add SYS_PTRACE --memory="4gb" -d -p 80:80 jhpyle/docassemble
|
|
62
|
-
shell: bash
|
|
63
|
-
- name: "ALKiln github_server: Wait for server to start"
|
|
64
|
-
run: |
|
|
65
|
-
# ALKiln github_server: Wait for server to start
|
|
66
|
-
|
|
67
|
-
# Reset the SECONDS variable
|
|
68
|
-
SECONDS=0
|
|
69
|
-
# Wait 1 minute before pinging the server constantly
|
|
70
|
-
sleep 60
|
|
71
|
-
|
|
72
|
-
response="start"
|
|
73
|
-
|
|
74
|
-
while [[ $response != *"200"* ]]; do
|
|
75
|
-
echo "Time elapsed: $SECONDS seconds"
|
|
76
|
-
|
|
77
|
-
# Check if max seconds till loading has passed
|
|
78
|
-
if [[ $SECONDS -ge $MAX_SECONDS_FOR_DOCKER ]]; then
|
|
79
|
-
echo "ALKiln GitHub Server Error: Timed out waiting for docker container to serve the site. If you want to give your docker container more timem to install, set the MAX_SECONDS_FOR_DOCKER input for this action."
|
|
80
|
-
exit 1
|
|
81
|
-
fi
|
|
82
|
-
|
|
83
|
-
# Set the variable to a new string value in each iteration
|
|
84
|
-
response=$(curl -o /dev/null -s -w "%{http_code}\n" http://localhost:80/health_check?ready=1)
|
|
85
|
-
echo "response is $response"
|
|
86
|
-
|
|
87
|
-
# Check if the string includes the desired text
|
|
88
|
-
if [[ $response == *"200"* ]]; then
|
|
89
|
-
echo "Success! The docker container is ready!"
|
|
90
|
-
else
|
|
91
|
-
echo "The docker container isn't ready yet. Will check again in 30 seconds."
|
|
92
|
-
sleep 30
|
|
93
|
-
fi
|
|
94
|
-
|
|
95
|
-
done
|
|
96
|
-
shell: bash
|
|
97
|
-
|
|
98
|
-
# Don't rely on the environment's version of python
|
|
99
|
-
- uses: actions/setup-python@v4
|
|
100
|
-
with:
|
|
101
|
-
python-version: '3.10'
|
|
102
|
-
- run: pip install docassemblecli
|
|
103
|
-
shell: bash
|
|
104
|
-
# Install the current directory onto the docassemble server
|
|
105
|
-
- run: dainstall . --apiurl http://localhost --apikey $DA_ADMIN_API_KEY
|
|
106
|
-
shell: bash
|
|
107
|
-
|
|
108
|
-
# TODO: Upload artifacts that subscribers can download on the Actions summary page
|
|
109
|
-
- name: "ALKiln github_server: Docker logs"
|
|
110
|
-
if: ${{ always() }}
|
|
111
|
-
run: |
|
|
112
|
-
# Should this name have a date/time attached? The logs themselves have timestamps
|
|
113
|
-
echo "$(docker logs docassemble_container)" > /tmp/alkiln_docker_logs.txt
|
|
114
|
-
shell: bash
|
|
115
|
-
|
|
116
|
-
- name: "ALKiln github_server: Get folder name with date and time"
|
|
117
|
-
if: ${{ always() }}
|
|
118
|
-
run: |
|
|
119
|
-
echo "GITHUB_SERVER_ARTIFACT_NAME=alkiln-github-server-$(date +'%Y-%m-%d at %Hh%Mm%Ss' -u)UTC" >> $GITHUB_ENV
|
|
120
|
-
shell: bash
|
|
121
|
-
- name: "ALKiln github_server: Upload artifacts folder"
|
|
122
|
-
if: ${{ always() }}
|
|
123
|
-
uses: actions/upload-artifact@v3
|
|
124
|
-
with:
|
|
125
|
-
name: ${{ env.GITHUB_SERVER_ARTIFACT_NAME }}
|
|
126
|
-
path: /tmp/alkiln_docker_logs.txt
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const session_vars = require('../utils/session_vars');
|
|
4
|
-
const log = require('../utils/log');
|
|
5
|
-
const fg = require('fast-glob');
|
|
6
|
-
|
|
7
|
-
const server_install = async () => {
|
|
8
|
-
session_vars.save_install_method(`server`);
|
|
9
|
-
|
|
10
|
-
let current_dir = process.cwd();
|
|
11
|
-
let path = `${ current_dir }/docassemble/*`;
|
|
12
|
-
let dirs = fg.sync(
|
|
13
|
-
[ path ],
|
|
14
|
-
{
|
|
15
|
-
suppressErrors: true,
|
|
16
|
-
onlyDirectories: true
|
|
17
|
-
}
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
let folders = dirs.map(function (dir) { return dir.split('/').pop(); })
|
|
21
|
-
|
|
22
|
-
let chosen_folder = folders[0];
|
|
23
|
-
if ( folders.length === 0 ) {
|
|
24
|
-
let msg = `There are 0 folders at ${path}. Tests won't run.`;
|
|
25
|
-
log.error({ type: `setup`, data: msg })
|
|
26
|
-
throw new ReferenceError( msg );
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if ( folders.length > 1 ) {
|
|
30
|
-
log.warn({
|
|
31
|
-
type: `setup`,
|
|
32
|
-
data: `There are ${folders.length} folders at ${path}: "${folders.join('", "')}". ALKiln chose to use the folder "${chosen_folder}".`
|
|
33
|
-
})
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
console.log(`\n===========\nchosen_folder: ${chosen_folder}\n===========\n`);
|
|
37
|
-
session_vars.save_repo_folder_name( chosen_folder );
|
|
38
|
-
}; // Ends server_install();
|
|
39
|
-
|
|
40
|
-
server_install();
|